var UCD = UCD || {
    Core: jQuery
};

(function(NS, $) {
    var TIMERS = new NS.TimerManager();

    var isSVG = NS.Cords.prototype.isSVG();

    /**
     * 折线图
     *
     * 1. 支持曲线、折线、面积三种图表的配置;
     * 2. 支持水平垂直模式展现;
     * 3. 支持整体自适应缩放;
     * 4. 折线X轴位置根据容器大小自适应;
     * 5. 支持不同区域块设置;
     * 6. 可以设定目标线;
     * 7. X轴文本超长时使用奇偶落差排版
     * 8. 支持Y1、Y2坐标的配置;
     * 9. 设置图例的显示;
     * 10. 支持负值的设置;
     * 11. 支持虚线设置;
     * 12. 支持对空值的处理;<br>
     * 13. 支持十字线功能;
     * 14. 支持添加、删除的功能;<br>
     * 15. 支持gray/black两种风格的换肤;
     * 16. 支持图例事件回调:hover、click;
     * 17. 支持柱子事件回调:hover、click;
     * 18. 指定每组数据的折线类型。
     * 
     * @smartueExample 基本用法 charts/line/basic.html
     * @smartueExample Y轴阈值 charts/line/y_range.html
     * @smartueExample X轴阈值 charts/line/x_range.html
     * @smartueExample 目标线功能 charts/line/goals_line.html
     * @smartueExample 多组数据 charts/line/multi_series.html
     * @smartueExample 十字线功能 charts/line/cross_line.html
     * @smartueExample Y2次坐标轴 charts/line/y2.html
     * @smartueExample 指定不同折线类型 charts/line/multi_line_types.html
     * 
     * @memberOf UCD
     * @class Line
     * 
     * @param {String|Object} container - jQuery selector
     * @param {Boolean} [isVertical = false] true为纵折线 默认为false
     * @param {Boolean} [isArea = false] 面积图
     * @param {Boolean} [isComPlex = false] 复合图
     */       
    NS.Line = function(container, isVertical, isArea, isComPlex) {
        this._settings = {
            container: $(container),
            root: $("<div class='UCDChart'></div>"),
            infoLayer: $("<div class='infoLayer'></div>"),

            NO_DATA: "no data loaded.", 
            TRANSITION: "all 0.5s ease-out", 
            DOT_TEXT_FILL: "#9E9E9E", 
            DOT_TEXT_ANCHOR: "middle", 

            crossLineColor: "#CCC", 
            crossCircleStrokeWidth: 0, 
            crossCircleRadius: 8, 
            crossCircleSelectRadius: 3, 
            crossCircleFill: "#FFF", 

            circleStrokeOpacity: 1, 
            circleSelectedStrokeOpacity: 1, 

            legendTextColor: "#9E9E9E", 
            legendTextSelectColor: "#666", 

            smoothTolerance: 30, 
            smoothTension: 3, // 如果超出了坐标轴之外，可以改大。

            aimLine: [], //目标线
            isAim: false, //是否启用目标线分区域块功能
            isSmooth: true, //是否为弧线
            isCircle: true, //是否有圆点
            animateSpace: 10, //动画从至高点到当前位置间距
            isAnimate: true, //是否启用动画
            animateType: "y", //动画类型 x/y默认y
            animateTime: 2000, //动画执行时间
            opacity: 0.6, //面积图初始透明度
            selectOpacity: 0.8, //面积图选中状态时的透明度
            strokeWidth: 2, //线的粗细
            strokeWidthSelect: 3, //线选中状态的粗细
            circleR: 3, //dot半径
            circleRSelect: 4, //dot选中半径
            circleFillColor: "#FDFD00", 
            isGrid: false, //是否设置网格
            isSide: false, //是否贴边显示
            isShowText: false, //是否显示tip文本
            isNoBeyond: true, //是否让图表不超出最顶边
            isCrossTypeShow: false, //移动显示十字线功能时是否持续显示
            emptyValue: 0, //设置空值的默认值
            emptyColor: "red", //设置空值的颜色
            orientation: !!isVertical, //设置图片显示方位
            isComPlex: !!isComPlex, //当前创建是否为复合图表默认false
            isLadder: true, // 梯形折线图
            // lineTypes: ['line', 'smooth', 'smooth area', 'ladder'], // 指定每组数据的折线类型, 'line','smooth','ladder','area' + 'animate'
            lineTypes: [], 
            isNormalLine: isLineType(this, 'line', true, undefined), 
            isSmoothLine: isLineType(this, 'smooth', false, 'isSmooth'), 
            isLadderLine: isLineType(this, 'ladder', false, undefined), 
            isAreaLine: isLineType(this, 'area', false, 'isArea'), 
            isNeedAnimate: isLineType(this, 'animate', false, 'isAnimate'), 
            isArea: !!isArea //是否为面积图表默认false
        };
        var settings = this._settings;
        settings.self = this;
        settings.root.addClass(NS.getStyle()); //设置风格
        settings.itemsArray = []; //存储折线数据
        settings.circleArray = []; //存储当屏圆点数据
        settings.colorArray = []; //存储颜色集
        settings.eMax = 0; //如当前模式为复合图表且是单坐标，最大值使用该对象
        settings.crossArray = []; //存储十字线数据
        settings.padding = 10; //图表padding设置
        settings.isYRuleLine = true; //默认显示坐标线
        settings.data = [];
        settings.hiddenIndexes = [];

        settings.frags = $("<div class='Frags'></div>");
        settings.cord = new NS.Cords(settings.root);
        settings.Source = settings.cord._settings.Source;

        if (isVertical) {
            settings.root.addClass("vertical");
        }
        if (settings.cord.isValidCSS3()) {
            settings.root.addClass("CSS3");
        }
        if (!isComPlex) {
            settings.container.empty().append(settings.root);
            settings.root.append(settings.infoLayer, settings.frags);
            _infoLayer(settings, settings.NO_DATA);
        } else {
            settings.container.append(settings.frags);
            settings.cord._settings.comPlexContainer = settings.container;
            settings.frags.css({
                "border": "none"
            });
        }

        settings.cord._settings.isComPlex = settings.isComPlex;
        settings.cord._settings.padding = settings.padding;
        if (isSVG) {
            settings.svg = settings.cord.createElement("svg", {
                version: "1.1"
            }, settings.frags[0]);
            $(settings.svg).css({
                "position": "absolute"
            });
            settings.lineTotal = settings.cord.createElement("g", null, settings.svg);
            $(settings.lineTotal).css({
                "-webkit-transition": settings.TRANSITION
            });
        } else {
            settings.svg = $("<div></div>").css("position", "absolute").appendTo(settings.frags)[0];
            settings.lineTotal = $("<div></div>").appendTo(settings.svg).css({
                "-webkit-transition": settings.TRANSITION
            })[0];
        }
    };

    // TODO: why not using Cords#setAttributes
    function setAttr(elem, key, value) {
        if (isSVG || key !== 'd') {
            elem.setAttribute(key, value);
        } else {
            elem['path'] = value;
        }
    }

    /**
     * 指定每组数据的折线类型
     * 
     * @param  {String}  type 'line','smooth','ladder','area' + 'animate'
     * @param  {Boolean}  defaultVal    默认值
     * @param  {String}  key    key值
     * @param  {Number}  i    每组数据
     * @return {Boolean}      折线类型
     */
    function isLineType(self, type, defaultVal, key) {
        return function(i) {
            var t = self._settings.lineTypes[i];
            return t ? (t.indexOf(type) !== -1) : (key !== undefined ? self._settings[key] : defaultVal);
        };
    }

    //修改目标线容器位置
    function _modifyAimLine(settings) {
        if (!settings.isAim) { // 如果不支持目标线就直接返回
            return false;
        }

        var yHeight = 0;
        var xHeight = 0;
        settings.xPArray = []; //x轴区域位置
        settings.aimLineArray = settings.aimPosition == "x" ? settings.aimLine : settings.aimLine.sort(function(a, b) {
            return a < b ? 1 : -1;
        });
        if (settings.aimPosition == "x") {
            for (var y = 0; y < settings.aimLine.length; y++) {
                for (var x = 0; x < settings.xData.length; x++) {
                    if (settings.xData[x] == settings.aimLine[y]) {
                        settings.xPArray.push(settings.xPoses[x]);
                        break;
                    }
                }
            }
        }
        for (var i = 1; i < settings.aimLineArray.length + 1; i++) {
            var value = settings.aimLineArray[i - 1];
            var y = settings.aimPosition == "x" ? settings.xPArray[i - 1] : _getTall(settings, value, settings.y1Data);
            if (!settings.orientation) {
                if (settings.aimPosition == "x") {
                    if (i == 1) {
                        settings.cord.setAttributes(settings.itemsArray[i].rect, {
                            width: y - yHeight + settings.padding,
                            height: settings.height + settings.padding * 2,
                            x: yHeight,
                            y: 0
                        });
                    } else {
                        // IE BUG
                        settings.itemsArray[i] && settings.cord.setAttributes(settings.itemsArray[i].rect, {
                            width: y - yHeight,
                            height: settings.height + settings.padding * 2,
                            x: yHeight + settings.padding,
                            y: 0
                        });
                    }
                } else {
                    if (i == 1) {
                        settings.cord.setAttributes(settings.itemsArray[i].rect, {
                            width: settings.width + settings.maxWidth,
                            height: y - yHeight + settings.padding,
                            x: 0,
                            y: yHeight
                        });
                    } else {
                        // TODO: resize bug, settings.itemsArray[i] is null
                        settings.cord.setAttributes(settings.itemsArray[i].rect, {
                            width: settings.width + settings.maxWidth,
                            height: y - yHeight,
                            x: 0,
                            y: yHeight + settings.padding
                        });
                    }
                }
                yHeight = y;
            } else {
                if (settings.aimPosition == "x") {
                    if (i == 1) {
                        settings.cord.setAttributes(settings.itemsArray[i].rect, {
                            width: settings.width + settings.maxWidth,
                            height: y - xHeight + settings.padding,
                            x: 0,
                            y: xHeight
                        });
                    } else {
                        settings.cord.setAttributes(settings.itemsArray[i].rect, {
                            width: settings.width + settings.maxWidth,
                            height: y - xHeight,
                            x: 0,
                            y: xHeight + settings.padding
                        });
                    }
                } else {
                    settings.cord.setAttributes(settings.itemsArray[i].rect, {
                        width: settings.width - y - yHeight,
                        height: settings.height + settings.padding * 2,
                        x: y + settings.padding,
                        y: 0
                    });
                }
                yHeight = yHeight + settings.width - y - yHeight;
                xHeight = y;
            }
        }
        if (!settings.orientation) {
            if (settings.aimPosition == "x") {
                settings.cord.setAttributes(settings.rect, {
                    width: settings.width - yHeight + settings.padding,
                    height: settings.height + settings.padding * 2,
                    x: yHeight + settings.padding,
                    y: 0
                });
            } else {
                settings.cord.setAttributes(settings.rect, {
                    width: settings.width + settings.maxWidth,
                    height: settings.height - yHeight + settings.padding,
                    x: 0,
                    y: yHeight + settings.padding
                });
            }
        } else {
            if (settings.aimPosition == "x") {
                settings.cord.setAttributes(settings.rect, {
                    width: settings.width + settings.maxWidth,
                    height: settings.height - xHeight + settings.padding,
                    x: 0,
                    y: xHeight + settings.padding
                });
            } else {
                settings.cord.setAttributes(settings.rect, {
                    width: settings.width - yHeight + settings.padding,
                    height: settings.height + settings.padding * 2,
                    x: 0,
                    y: 0
                });
            }
        }
    }

    var __uuid = 0;
    function _createID() {
        return 'ucd_charts_line_' + (++__uuid);
    }

    //目标线功能 只支持一条数据
    function _aimLine(settings) {
        settings.aimCircleArray = []; //存储目标功能新添加的圆点数据
        var yHeight = 0;
        var xHeight = 0;
        if (settings.itemsArray.length > 1 || settings.aimLine === 0) {
            return;
        }
        settings.aimLineArray = settings.aimPosition == "x" ? settings.aimLine : settings.aimLine.sort(function(a, b) {
            return a < b ? 1 : -1;
        });
        settings.xPArray = []; //x轴区域位置
        if (settings.aimPosition == "x") {
            for (var y = 0; y < settings.aimLine.length; y++) {
                for (var x = 0; x < settings.xData.length; x++) {
                    if (settings.xData[x] == settings.aimLine[y]) {
                        settings.xPArray.push(settings.xPoses[x]);
                        break;
                    }
                }
            }
        }
        //折线遮罩层
        settings.lineShadeDefs = settings.cord.createElement("defs", null, settings.svg);
        for (var i = 0; i < settings.aimLineArray.length; i++) {
            var items = {};
            var idTime = _createID();
            items.value = settings.aimLineArray[i];
            var y = (settings.aimPosition == "x" ? settings.xPArray[i] || 0 : _getTall(settings, items.value, settings.y1Data)) || 0;
            var yValue;
            var hValue;
            var clippath = settings.cord.createElement("clipPath", {
                id: idTime
            }, settings.lineShadeDefs);
            if (!settings.orientation) {
                var h = y - yHeight < 0 ? 0 : y - yHeight;
                if (settings.aimPosition == "x") {
                    if (i === 0) {
                        items.rect = settings.cord.createElement("rect", {
                            width: h + settings.padding,
                            height: settings.height + settings.padding * 2,
                            x: yHeight,
                            y: 0
                        }, clippath);
                    } else {
                        items.rect = settings.cord.createElement("rect", {
                            width: h,
                            height: settings.height + settings.padding * 2,
                            x: yHeight + settings.padding,
                            y: 0
                        }, clippath);
                    }
                } else {
                    if (i === 0) {
                        items.rect = settings.cord.createElement("rect", {
                            width: settings.width + settings.maxWidth,
                            height: y - yHeight + settings.padding,
                            x: 0,
                            y: yHeight
                        }, clippath);
                    } else {
                        items.rect = settings.cord.createElement("rect", {
                            width: settings.width + settings.maxWidth,
                            height: y - yHeight,
                            x: 0,
                            y: yHeight + settings.padding
                        }, clippath);
                    }
                }
                if (!isSVG) {
                    if (settings.aimPosition == "x") {
                        items.lineCon = $("<div></div>").css({
                            "position": "absolute",
                            "overflow": "hidden",
                            "width": h,
                            "height": settings.height + settings.padding * 2,
                            "left": yHeight + settings.padding,
                            "top": 0
                        }).appendTo(settings.lineTotal);
                        items.lineTrans = $("<div></div>").css({
                            "position": "absolute",
                            "margin-left": -yHeight - settings.padding
                        }).appendTo(items.lineCon)[0];
                    } else {
                        items.lineCon = $("<div></div>").css({
                            "position": "absolute",
                            "overflow": "hidden",
                            "width": settings.width + settings.padding * 2,
                            "height": h,
                            "top": yHeight + settings.padding
                        }).appendTo(settings.lineTotal);
                        items.lineTrans = $("<div></div>").css({
                            "position": "absolute",
                            "margin-top": -yHeight - settings.padding
                        }).appendTo(items.lineCon)[0];
                    }
                }
                yValue = yHeight;
                hValue = y - yHeight;
                yHeight = y;
            } else {
                if (settings.aimPosition == "x") {
                    if (i === 0) {
                        items.rect = settings.cord.createElement("rect", {
                            width: settings.width + settings.maxWidth,
                            height: y - xHeight + settings.padding,
                            x: 0,
                            y: xHeight
                        }, clippath);
                    } else {
                        items.rect = settings.cord.createElement("rect", {
                            width: settings.width + settings.maxWidth,
                            height: y - xHeight,
                            x: 0,
                            y: xHeight + settings.padding
                        }, clippath);
                    }
                } else {
                    items.rect = settings.cord.createElement("rect", {
                        width: settings.width - y - yHeight,
                        height: settings.height + settings.padding * 2,
                        x: y + settings.padding,
                        y: 0
                    }, clippath);
                }

                if (!isSVG) {
                    if (settings.aimPosition == "x") {
                        items.lineCon = $("<div></div>").css({
                            "position": "absolute",
                            "overflow": "hidden",
                            "width": settings.width,
                            "height": y - xHeight,
                            "left": 0,
                            "top": xHeight + settings.padding
                        }).appendTo(settings.lineTotal);
                        items.lineTrans = $("<div></div>").css({
                            "position": "absolute",
                            "margin-top": -xHeight - settings.padding
                        }).appendTo(items.lineCon)[0];
                    } else {
                        items.lineCon = $("<div></div>").css({
                            "position": "absolute",
                            "overflow": "hidden",
                            "width": settings.width - y - yHeight,
                            "height": settings.height + settings.padding * 2,
                            "left": y + settings.padding,
                            "top": 0
                        }).appendTo(settings.lineTotal);
                        items.lineTrans = $("<div></div>").css({
                            "position": "absolute",
                            "margin-left": -y - settings.padding
                        }).appendTo(items.lineCon)[0];
                    }
                }
                yValue = 0;
                hValue = settings.width - y - yHeight;

                yHeight = yHeight + settings.width - y - yHeight;
                xHeight = y;
            }

            if (isSVG) {
                items.lineCon = settings.cord.createElement("g", {
                    "transform": "translate(0 0)",
                    "clip-path": "url(#" + idTime + ")"
                }, settings.lineTotal);
                items.lineTrans = settings.cord.createElement("g", {
                    "transform": "translate(0 0)"
                }, items.lineCon);
            }

            items.gLine = settings.cord.createElement("g", null, items.lineTrans);
            items.gCircle = settings.cord.createElement("g", null, items.lineTrans);
            if (settings.isShowText) {
                items.gText = settings.cord.createElement("g", null, items.lineTrans);
            }
            items.itemPathArray = settings.itemsArray[0].itemPathArray;
            items.startItemPath = settings.itemsArray[0].startItemPath;
            items.endItemPath = settings.itemsArray[0].endItemPath;
            items.itemPath = settings.itemsArray[0].itemPath;

            items.startItemPathSolid = settings.itemsArray[0].startItemPathSolid;
            items.endItemPathSolid = settings.itemsArray[0].endItemPathSolid;
            items.itemPathSolid = settings.itemsArray[0].itemPathSolid;

            var color = settings.colorArray[i]; //折线颜色
            var fillColor = settings.isAreaLine(i) ? color : 'none';
            items.line = settings.cord.createElement("path", {
                "fill": fillColor,
                "stroke": color,
                "cursor": "pointer"
            }, items.gLine);
            if (settings.isAreaLine(i)) {
                items.lineSolid = settings.cord.createElement("path", {
                    "fill": "none",
                    "stroke": color,
                    "stroke-width": settings.strokeWidth,
                    "ostroke-width": settings.strokeWidth,
                    "cursor": "pointer",
                    "filled": "f"
                }, items.gLine);
                settings.cord.setAttributes(items.line, {
                    "opacity": settings.opacity
                });
            }
            if (!settings.isAnimate) {
                settings.cord.setAttributes(items.line, {
                    "d": items.itemPath
                });
                if (settings.isAreaLine(i)) {
                    settings.cord.setAttributes(items.lineSolid, {
                        "d": items.itemPathSolid
                    });
                }
            }
            //设置动画
            $(items.lineTrans).css({
                "-webkit-transition": settings.TRANSITION
            });

            var circleArray = [];
            for (var j = 0; j < settings.circleArray[0].length; j++) {
                var cItems = {};
                var cObj = settings.circleArray[0][j];
                cItems.x = cObj.x;
                cItems.y = cObj.y;
                cItems.startY = settings.height;
                cItems.endY = cObj.y - settings.animateSpace;
                cItems.value = cObj.value;
                cItems.color = color;
                var cx = cItems.x;
                var v = cObj.proValue;
                var reNum = /^\d*$/;
                var cirColor = ((v && !isNaN(v) && reNum.test(v)) || (parseInt(v) === 0) || typeof v == "number") ? color : settings.emptyColor;
                if (settings.isCircle) {
                    cItems.circle = settings.cord.createElement("circle", {
                        "cx": cx,
                        "cy": cItems.y,
                        "value": cItems.value,
                        "r": 3,
                        "fill": settings.circleFillColor,
                        "stroke": cirColor,
                        "stroke-width": 2,
                        'stroke-opacity': settings.circleStrokeOpacity
                    }, items.gCircle);

                    if (!isSVG && settings.circleStrokeOpacity < 1) {
                        settings.cord.createElement("stroke", {
                            "opacity": settings.circleStrokeOpacity
                        }, cItems.circle);
                    }

                    if (settings.isAnimate) {
                        $(cItems.circle).css("opacity", 0); // 使用jQuery设置opacity可以避免cords.setAttributes的干扰
                    }
                }
                if (settings.isShowText) {
                    var textCx = !settings.orientation ? cx : cx + 15;
                    var textCy = !settings.orientation ? cItems.y - 8 : cItems.y + 4;
                    if (isSVG) {
                        cItems.text = settings.cord.createElement("text", {
                            "x": textCx,
                            "y": textCy,
                            "fill": settings.DOT_TEXT_FILL,
                            "text-anchor": settings.DOT_TEXT_ANCHOR
                        }, items.gText);
                        cItems.text.textContent = cObj.value;
                    }
                    if (settings.isAnimate) {
                        $(cItems.text).css("opacity", 0);
                    }
                }
                circleArray.push(cItems);
            }
            settings.circleArray.push(circleArray);
            settings.itemsArray.push(items);
        }
        var time = _createID() + 1;
        var clippath = settings.cord.createElement("clipPath", {
            id: time
        }, settings.lineShadeDefs);
        if (!settings.orientation) {
            if (settings.aimPosition == "x") {
                // TODO:  + settings.maxWidth，这里只是简单的增加了clip的宽度，并没有真正的计算。
                settings.rect = settings.cord.createElement("rect", {
                    width: settings.width - yHeight + settings.padding + settings.maxWidth,
                    height: settings.height + settings.padding * 2,
                    x: yHeight + settings.padding,
                    y: 0
                }, clippath);
            } else {
                settings.rect = settings.cord.createElement("rect", {
                    width: settings.width + settings.maxWidth,
                    height: settings.height - yHeight + settings.padding * 2,
                    x: 0,
                    y: yHeight + settings.padding
                }, clippath);
            }
        } else {
            if (settings.aimPosition == "x") {
                settings.rect = settings.cord.createElement("rect", {
                    width: settings.width + settings.maxWidth,
                    height: settings.height - xHeight + settings.padding,
                    x: 0,
                    y: xHeight + settings.padding
                }, clippath);
            } else {
                settings.rect = settings.cord.createElement("rect", {
                    width: settings.width - yHeight + settings.padding,
                    height: settings.height + settings.padding * 2,
                    x: 0,
                    y: 0
                }, clippath);
            }
        }
        settings.cord.setAttributes(settings.lineCon, {
            "clip-path": "url(#" + time + ")"
        });
    }

    //yType:Y坐标类型(y1/y2),支持数据可分别参照y1或y2坐标
    function _setData(settings, data, yType) {
        settings.aimLineArray = [];
        settings.controlP1 = [];
        settings.controlP2 = [];
        settings.startControlP1 = [];
        settings.startControlP2 = [];
        settings.startPreControl2 = [];
        settings.preControl2 = [];
        settings.preControl1 = [];
        settings.sItem = [];
        settings.eItem = [];
        if (yType == "y1") {
            $(settings.lineShadeDefs).remove();
            $(settings.lineTotal).empty();

            settings.width = settings.frags.width();
            settings.height = (settings.isNoBeyond && !settings.orientation) ? (settings.frags.height() + (settings.cord._settings.totalNum || 0)) : settings.frags.height();
            settings.maxWidth = 10000;
            settings.cord.setAttributes(settings.svg, {
                width: settings.container.outerWidth(true),
                height: settings.height + settings.padding * 2
            });
            var top = (settings.isNoBeyond && !settings.orientation) ? -settings.cord._settings.totalNum : 0;
            $(settings.svg).css({
                "left": -settings.padding,
                "top": top - settings.padding
            }).attr("leftAttr", -settings.padding);
            settings.cord._settings.cordContent.css("left", 0);
            settings.scrollLeft = settings.cord._settings.scrollLeft = 0;

            if (!isSVG) {
                settings.lineCon = $("<div></div>").css({
                    "position": "absolute",
                    "width": settings.width + settings.padding * 2,
                    "height": settings.height,
                    "top": settings.padding
                }).appendTo(settings.lineTotal);
                settings.lineTrans = $("<div></div>").css({
                    "position": "absolute",
                    "margin-top": -settings.padding
                }).appendTo(settings.lineCon)[0];
            } else {
                settings.lineCon = settings.cord.createElement("g", {
                    "transform": "translate(0 0)"
                }, settings.lineTotal);
                settings.lineTrans = settings.cord.createElement("g", {
                    "transform": "translate(0 0)"
                }, settings.lineCon);
            }
            settings.gLine = settings.cord.createElement("g", null, settings.lineTrans);
            settings.gCircle = settings.cord.createElement("g", null, settings.lineTrans);
            if (settings.isShowText) {
                settings.gText = settings.cord.createElement("g", null, settings.lineTrans);
            }
            var dataLength = settings.data ? settings.data.length : 0;
            settings.xPoses = settings.cord.getMainPoses(dataLength); //获取X坐标集
            settings.xSpaceWidth = settings.xPoses[1] - settings.xPoses[0];
            settings.firstPoses = settings.xPoses[0];
            settings.yPoses = _getTall(settings, data, settings.y1Data);
        } else {
            settings.yPoses = _getTall(settings, data, settings.y2Data);
        }

        settings._bbox = _calcBBox(settings.xPoses, settings.yPoses, settings.padding);

        if (data && data.length > 0) {
            for (var i = 0; i < data.length; i++) {
                _addNode(settings, data[i], i, null, "create", null, yType);
            }

            if (settings.isAim) {
                _aimLine(settings); //折线目标线
            }
            if (settings.isAnimate) {
                _initAnimate(settings);
            }
        }
        //触发X轴动画
        if (settings.animateType == "x" && isSVG) {
            //折线遮罩层
            settings.lineShadeDefsX = settings.cord.createElement("defs", null, settings.svg);
            var idTime = _createID();
            var clippath = settings.cord.createElement("clipPath", {
                id: idTime
            }, settings.lineShadeDefsX);
            var rect = settings.cord.createElement("rect", {
                width: 0,
                height: settings.height + settings.padding * 2,
                x: 0,
                y: 0,
                "desc": "11"
            }, clippath);
            settings.cord.setAnimate(rect, 0, settings.width + settings.padding * 2 + 100, "width", 1, settings.animateTime / 1000);
            settings.cord.setAttributes(settings.lineTotal, {
                "clip-path": "url(#" + idTime + ")"
            });
        } else if (settings.animateType == "x" && !isSVG) {
            $(settings.lineTotal).css({
                "width": 0,
                "height": settings.height + settings.padding * 2,
                "overflow": "hidden",
                "position": "absolute"
            });
            $(settings.lineTotal).animate({
                "width": settings.width + settings.padding * 2
            }, settings.animateTime);
        }
        settings.self.setOnHover();
        settings.self.setOnClick();
        settings.self.setLegendOnHover();
        settings.self.setLegendOnClick();
        settings.self.setDotOnHover();
        settings.self.setDotOnClick();
    }

    //动画控制
    function _animate(settings, self, index, itemPath, circleArray) {
        var setTime1 = null;
        var flag = false;
        var isSmooth = settings.isSmoothLine(index), isLadder = settings.isLadderLine(index);
        var itPath = isLadder ? [itemPath] : (isSmooth ? itemPath.split("C") : itemPath.split("L")); // TODO: split path
        var itPathSolid = isSmooth ? itemPath.split("C") : itemPath.split("L");
        var newArray = []; //过渡处理Y值
        var itemArray = []; //存储Y值
        var itemXArray = []; //存储弧线X值

        var opacity = 0;
        var maxVal = 0;
        var areaLastVal = ""; //面积图表结尾
        var aVal = "";
        var height = settings.height + settings.padding;
        if (settings.isAreaLine(index)) {
            settings.cord.setAttributes(self.line, {
                "opacity": settings.opacity
            });
        }
        for (var iIndex = 0; iIndex < itPath.length; iIndex++) {
            // TODO: IE8 animate bug, ladder line path is Mx,y Lxx,y Lxx,yy e
            if (isSmooth) {
                if (iIndex == itPath.length - 1 && settings.isAreaLine(index)) {
                    areaLastVal = itPath[iIndex].substring(itPath[iIndex].indexOf("L"));
                    itPath[iIndex] = itPath[iIndex].substring(0, itPath[iIndex].indexOf("L"));
                    itPathSolid[iIndex] = itPathSolid[iIndex].substring(0, itPathSolid[iIndex].indexOf("L"));
                }
                var itemInd = itPath[iIndex].split(" ");
                var yArray = [];
                var nArray = [];
                var xArray = [];
                for (var i = 0; i < itemInd.length; i++) {
                    var ind = itemInd[i].split(",");
                    var xVal = ind[0];

                    xArray.push(xVal);
                    yArray.push(ind[1]);
                    nArray.push(height);
                }
                itemArray.push(yArray);
                itemXArray.push(xArray);
                newArray.push(nArray);
            } else if (isLadder) {
                // do not animate this
            } else {
                itemArray.push( itPath[iIndex].substring( itPath[iIndex].indexOf(",") + 1 ) );
                newArray.push(height);
            }
        }
        var anNumber = Math.round(height / 40);

        // 动画原理：修改path路径中的y值
        function animateInterval() {
            opacity += 0.1;
            if (settings.data.length > 1) {
                for (var i = 0; i < itPath.length; i++) {
                    //如果为弧线
                    if (isSmooth) {
                        var itemStr = "";
                        for (var j = 0; j < itemArray[i].length; j++) {
                            var yStr = itemArray[i][j];
                            var text = itPath[i].split(",");

                            //低到高增长
                            if (parseInt(yStr) < parseInt(newArray[i][j])) {
                                if (parseInt(yStr) >= newArray[i][j] - Math.round((height - parseInt(yStr)) / anNumber)) {
                                    newArray[i][j] = parseInt(yStr);
                                } else {
                                    newArray[i][j] = newArray[i][j] - Math.round((height - parseInt(yStr)) / anNumber);
                                }
                                flag = true;
                            } else {
                                flag = false;
                            }
                            itemStr += itemXArray[i][j] + "," + (newArray[i][j]) + " ";
                        }
                        itPath[i] = itemStr;
                        itPathSolid[i] = itemStr;
                        if (i == itPath.length - 1 && settings.isAreaLine(index)) {
                            aVal = areaLastVal;
                        }
                    } else if (isLadder) {
                        flag = true; // 结束动画
                    } else {
                        var yStr = itemArray[i];
                        var text = itPath[i].split(",");

                        if (parseInt(yStr) < parseInt(newArray[i])) {
                            if (parseInt(yStr) >= newArray[i] - Math.round((height - parseInt(yStr)) / anNumber)) {
                                newArray[i] = parseInt(yStr);
                            } else {
                                newArray[i] = newArray[i] - Math.round((height - parseInt(yStr)) / anNumber);
                            }
                            flag = true;
                        } else {
                            flag = false;
                        }
                        itPath[i] = text[0] + "," + newArray[i];
                        itPathSolid[i] = text[0] + "," + newArray[i];
                    }
                }
                var pathI = isLadder ? itPath[0] : (isSmooth ? itPath.join("C") + aVal : itPath.join("L"));
                setAttr(self.line, "d", pathI);
                
                if (settings.isAreaLine(index)) {
                    var pathSolid = isSmooth ? itPathSolid.join("C") : itPathSolid.join("L");
                    setAttr(self.lineSolid, "d", pathSolid);
                }
            }

            if (opacity < 1 || flag) {

            } else {
                TIMERS.clearInterval(setTime1);
                for (var j = 0; j < settings.itemsArray.length; j++) {
                    for (var n = 0; n < settings.circleArray[j].length; n++) {
                        var cItem = settings.circleArray[j][n];
                        if (settings.isCircle) {
                            $(cItem.circle).css("opacity", 1);
                        }
                        if (settings.isShowText) {
                            $(cItem.text).css("opacity", 1);
                        }
                    }

                }
            }
        }

        setTime1 = TIMERS.setInterval(animateInterval, 50);
    }

    //初始化动画
    /*SVG:利用Animate标签去控制动画,注意的是Animate标签begin属性需要设置成indefinite,
	创建该动画标签时即执行该动画操作。
	动画执行过程先从最低点到最高点，然后从最高点到实际点。
	*/
    function _initAnimate(settings) {
        var opacity, isAreaLine = false;
        if ((isSVG ) ) {
            var time = settings.data.length > 1 ? 800 : 0;
            for (var j = 0; j < settings.itemsArray.length; j++) {
                isAreaLine = settings.isAreaLine(j);
                opacity = isAreaLine ? settings.opacity : 1;
                var objItem = settings.itemsArray[j];
                //最低点到最高点
                settings.cord.setAnimate(settings.itemsArray[j].line, 0, opacity / 2, "opacity", 2, 0.5);
                settings.cord.setAnimate(settings.itemsArray[j].line, objItem.startItemPath, objItem.endItemPath, "d", 2, 0.5);
                if (isAreaLine) {
                    settings.cord.setAnimate(settings.itemsArray[j].lineSolid, objItem.startItemPathSolid, objItem.endItemPathSolid, "d", 2, 0.5);
                    settings.cord.setAnimate(settings.itemsArray[j].lineSolid, 0, 1, "opacity", 2, 0.5);
                }
            }

            TIMERS.setTimeout(function() {
                for (var j = 0; j < settings.itemsArray.length; j++) {
                    isAreaLine = settings.isAreaLine(j);
                    opacity = isAreaLine ? settings.opacity : 1;
                    var objItem = settings.itemsArray[j];
                    //最高点到实际点
                    // TODO: bug, null 动画过程中切换，会出现null
                    settings.cord.setAnimate(settings.itemsArray[j].line, opacity / 2, opacity, "opacity", 4, 0.3);
                    settings.cord.setAnimate(settings.itemsArray[j].line, objItem.endItemPath, objItem.itemPath, "d", 4, 0.3);
                    if (isAreaLine) {
                        settings.cord.setAnimate(settings.itemsArray[j].lineSolid, objItem.endItemPathSolid, objItem.itemPathSolid, "d", 4, 0.3);
                    }
                    setAttr(settings.itemsArray[j].line, "d", objItem.itemPath);
                    if (isAreaLine) {
                        setAttr(settings.itemsArray[j].lineSolid, "d", objItem.itemPathSolid);
                        setAttr(settings.itemsArray[j].line, "opacity", settings.opacity);
                    }
                }
            }, 500);

            TIMERS.setTimeout(function() {
                for (var j = 0; j < settings.itemsArray.length; j++) {
                    for (var n = 0; n < settings.circleArray[j].length; n++) {
                        var cItem = settings.circleArray[j][n];
                        if (settings.isCircle) {
                            $(cItem.circle).css("opacity", 1);
                        }
                        if (settings.isShowText) {
                            $(cItem.text).css("opacity", 1);
                        }
                    }
                }
            }, time);
        } else {
            for (var i = 0; i < settings.itemsArray.length; i++) {
                var itemPath = settings.itemsArray[i].itemPath;
                _animate(settings, settings.itemsArray[i], i, itemPath, settings.circleArray);
            }
        }
    }

    //暂时只支持移除第一条数据
    function _removeNode(settings, index, active) {
        for (var n = 0; n < settings.circleArray.length; n++) {
            $(settings.circleArray[n][index].circle).remove();
            $(settings.circleArray[n][index].text).remove();
            settings.circleArray[n].splice(index, 1);
            settings.itemsArray[n].itemPathArray = [];
        }

        for (var i = 0; i < settings.data.length; i++) {
            _addNode(settings, settings.data[i], i, null, "modify");
        }
    }

    function _getPathPosition(settings, items) {
        var rate = settings.xSpaceWidth / settings.smoothTension;
        var spinner = {
            cy1: 0,
            cy2: 0
        }; //Y坐标微调
        var offset = {
            x: 0,
            y: 0
        };
        var beta = 0;

        var it = items;
        var afterXY;
        var beforeXY;
        if (!settings.orientation) {
            beforeXY = {
                x: settings.xPoses[it.index - 1],
                y: settings.yPoses[it.index - 1] ? settings.yPoses[it.index - 1].value[it.i] : settings.yPoses[it.index].value[it.i]
            };
        } else {
            beforeXY = {
                x: settings.yPoses[it.index - 1] ? settings.yPoses[it.index - 1].value[it.i] : settings.yPoses[it.index].value[it.i],
                y: settings.xPoses[it.index - 1]
            };
        }
        if (settings.yPoses[it.index + 1]) {
            if (!settings.orientation) {
                afterXY = {
                    x: settings.xPoses[it.index + 1],
                    y: settings.yPoses[it.index + 1].value[it.i]
                };
            } else {
                afterXY = {
                    x: settings.yPoses[it.index + 1].value[it.i],
                    y: settings.xPoses[it.index + 1]
                };
            }
        }
        if (it.dataLength == 1 || it.index + 1 == settings.xPoses.length) {
            if (!settings.orientation) {
                var y = settings.yPoses[it.index - 1] ? settings.yPoses[it.index - 1].value[it.i] : settings.yPoses[it.index].value[it.i];
                var yValue = settings.yPoses[it.index - 2] ? settings.yPoses[it.index - 2] : settings.yPoses[it.index - 1];
                if (yValue) {
                    y = yValue.value[it.i];
                }
                beforeXY = {
                    x: settings.xPoses[it.index - 2] ? settings.xPoses[it.index - 2] : settings.xPoses[it.index - 1],
                    y: y
                };
                afterXY = {
                    x: settings.xPoses[it.index],
                    y: settings.yPoses[it.index].value[it.i]
                };
            } else {
                var x = settings.yPoses[it.index - 1] ? settings.yPoses[it.index - 1].value[it.i] : settings.yPoses[it.index].value[it.i];
                var yValue = settings.yPoses[it.index - 2] ? settings.yPoses[it.index - 2] : settings.yPoses[it.index - 1];
                if (yValue) {
                    x = yValue.value[it.i];
                }
                beforeXY = {
                    x: x,
                    y: settings.xPoses[it.index - 2] ? settings.xPoses[it.index - 2] : settings.xPoses[it.index - 1]
                };
                afterXY = {
                    x: settings.yPoses[it.index].value[it.i],
                    y: settings.xPoses[it.index]
                };
            }
        }

        var crest = items.y > afterXY.y && items.y > beforeXY.y; //峰
        var vale = items.y < afterXY.y && items.y < beforeXY.y; //谷

        if (settings.orientation) {
            crest = items.x > afterXY.x && items.x > beforeXY.x; //峰
            vale = items.x < afterXY.x && items.x < beforeXY.x; //谷	
        }
        if (crest || vale) { //波峰波谷
            if (!settings.orientation) {
                if (settings.height - items.y > settings.smoothTolerance) {
                    beta = Math.atan((afterXY.y - beforeXY.y) / (afterXY.x - beforeXY.x));
                    offset = {
                        x: rate,
                        y: rate * Math.sin(beta)
                    };
                } else {
                    offset = {
                        x: rate,
                        y: 0
                    };
                }
            } else {
                if (settings.width - items.x > settings.smoothTolerance) {
                    beta = Math.atan((afterXY.x - beforeXY.x) / (afterXY.y - beforeXY.y));
                    offset = {
                        x: rate * Math.sin(beta),
                        y: rate
                    };
                } else {
                    offset = {
                        x: 0,
                        y: rate
                    };
                }
            }
        } else { //其他类型  前后点连线上取me.rate的长度
            if (!settings.orientation) {
                beta = Math.atan((afterXY.y - beforeXY.y) / (afterXY.x - beforeXY.x));
                offset = {
                    x: rate * Math.cos(beta),
                    y: rate * Math.sin(beta)
                };
            } else {
                beta = Math.atan((afterXY.x - beforeXY.x) / (afterXY.y - beforeXY.y));
                offset = {
                    x: rate * Math.sin(beta),
                    y: rate * Math.cos(beta)
                };
            }
        }

        // check neighbouring points' y values
        if (!settings.orientation) {
            var leftY = items.y - offset.y, 
                rightY = items.y + offset.y;

            if (leftY > beforeXY.y && leftY > items.y) {
                leftY = Math.max(beforeXY.y, items.y);
                rightY = 2 * items.y - leftY; // mirror of left control point
            } else if (leftY < beforeXY.y && leftY < items.y) {
                leftY = Math.min(beforeXY.y, items.y);
                rightY = 2 * items.y - leftY;
            }
            if (rightY > afterXY.y && rightY > items.y) {
                rightY = Math.max(afterXY.y, items.y);
                leftY = 2 * items.y - rightY;
            } else if (rightY < afterXY.y && rightY < items.y) {
                rightY = Math.min(afterXY.y, items.y);
                leftY = 2 * items.y - rightY;
            }

            // check bounding box
            // TODO: 如果校验了值反而会导致曲线不对
            // 因为我们的svg和frags并不是一样大
            var bbox = settings._bbox, minY = bbox[1], maxY = bbox[3]; 
            if (leftY < minY) {
                leftY = minY;
            } else if (leftY > maxY) {
                leftY = maxY;
            }

            if (rightY < minY) {
                rightY = minY;
            } else if (rightY > maxY) {
                rightY = maxY;
            }

            offset.y = items.y - leftY;
        } else {
            // TODO: 处理垂直情况
        }

        return [
            [ items.x - offset.x, leftY ], 
            [ items.x + offset.x, rightY ]
        ];
    }

    function _dashPath(xx, y, yy, dashLength) {
        dashLength = dashLength || 4;
        var len = Math.abs(y-yy), n = len/dashLength-1, step = y < yy ? dashLength : (-dashLength), parts = [];
        for (var i = 1; i < n; i+=2) {
            parts.push('M' + [xx, y + step*i].join(',') + 'L' + [xx, y + step*(i+1)].join(','));
        }
        return parts.join('');
    }

    /**
     * 根据前面一个点和当前一个点计算路径
     * 
     * @param  {Boolean} isLadder 是否为阶梯路径
     * @param  {Number} isFirst      isFirst
     * @param  {Number} isLast    isLast
     * @param  {Number} x      前面一个点
     * @param  {Number} y      前面一个点
     * @param  {Number} xx     当前一个点
     * @param  {Number} yy     当前一个点
     * @return {String}        path路径
     */
    function _linePath(isLadder, isFirst, isLast, x, y, xx, yy) {
        var path = [xx, yy].join(',');
        if (isFirst) {
            return path;
        }

        // TODO: return (isLadder ? ('L' + [xx, y].join(',')) : '') + 'L' + path; 连续直线，虚线
        // return (isLadder ? ('L' + [xx, y].join(',')) : '') + 'M' + path;
        // return (isLadder ? ('L' + [xx, y].join(',')) : '') + (i === (len-1) ? '' : _dashPath(xx, y, yy)) + 'M' + path;
        if (isLadder) {
            // return 'L' + [xx, y].join(',') + (isLast ? '' : _dashPath(xx, y, yy)) + 'M' + path;
            return 'L' + [xx, y].join(',') + _dashPath(xx, y, yy) + 'M' + path;
        }
        return 'L' + path; // 折线
    }

    // stroke-dasharray
    function _updateDashArray(items, prevItems) {
        if (!prevItems) { return; }
        items.strokeDashArray = items.strokeDashArray || [];
        items.strokeDashArray.push(Math.abs(items.x - prevItems.x));
        items.strokeDashArray.push(Math.abs(items.y - prevItems.y));
    }

    /*
     *获取Path路径 折线分为弧线和非弧线
     *非弧线画法: M X,Y L X,Y
     *弧线画法：三次贝塞尔曲线指令：C x1 y1, x2 y2, x y
     *第一个点坐标：距离前一个点的1/3;第二个点坐标:距离当前点的1/3;第二个点坐标:当前点
     *
     * offset： 计算辅助点
     * itemPathArray： 当前路径
     * startItemPathArray/endItemPathArray： 动画的开始路径，结束路径
     * startPreControl2/preControl2: 控制点pre
     * startControlP2/controlP2 控制点
     */
    function _getItemPath(settings, items) {
        var index = items.index; // 每组数据的第几个
        var i = items.i, iY2 = items.iY2; // 第几组数据
        var tmpPrevItems = settings._tmpPrevItemsArray[i + iY2] || {};
        
        // TODO: 考虑Y2坐标轴
        if (!settings.isSmoothLine(i + iY2)) {
            // var path = index == 0 ? (items.x + "," + items.y) : ("L" + items.x + "," + items.y);
            var isFirst = index === 0, 
                isLast = index === (items.dataLength - 1), 
                isLadder = settings.isLadderLine(i + iY2), 
                // isIE = !isSVG, 
                path = _linePath(isLadder, isFirst, isLast, tmpPrevItems.x, tmpPrevItems.y, items.x, items.y);

            items.itemPathArray.push(path);
            _updateDashArray(items, tmpPrevItems);

            if (items.startItemPathArray) {
                // var startPath = index == 0 ? (items.x + "," + items.startY) : ("L" + items.x + "," + items.startY);
                // var endPath = index == 0 ? (items.x + "," + items.endY) : ("L" + items.x + "," + items.endY);
                var startPath = _linePath(isLadder, isFirst, isLast, tmpPrevItems.x, tmpPrevItems.startY, items.x, items.startY);
                var endPath = _linePath(isLadder, isFirst, isLast, tmpPrevItems.x, tmpPrevItems.endY, items.x, items.endY);
                items.startItemPathArray.push(startPath);
                items.endItemPathArray.push(endPath);
            }
        } else {
            if (index === 0 && items.dataLength >= 1) { //起始点
                items.itemPathArray.push((items.x) + "," + (items.y)); //开始位置
                if (items.startItemPathArray) {
                    items.startItemPathArray.push(items.x + "," + items.startY + " ");
                    items.endItemPathArray.push((items.x) + "," + (items.y - settings.animateSpace));
                }
                settings.preControl2[i] = {
                    x: items.x,
                    y: items.y
                };
                settings.startPreControl2[i] = {
                    x: items.x,
                    y: items.startY
                };
            } else if (items.index < items.dataLength - 1) { //中间点
                var beforeValue = settings.data[index - 1].value[i];
                var afterValue = settings.data[index + 1].value[i];

                // 计算当前点左右两侧的控制点 [ [leftX, leftY], [rightY, rightY] ]
                var leftRightCP = _getPathPosition(settings, items);

                settings.controlP1[items.i].x = parseInt( leftRightCP[0][0] );
                settings.controlP1[items.i].y = parseInt( leftRightCP[0][1] );

                items.itemPathArray.push("C" + Math.round(settings.preControl2[i].x) + "," + Math.round(settings.preControl2[i].y) + 
                    " " + Math.round(settings.controlP1[i].x) + "," + Math.round(settings.controlP1[i].y) + 
                    " " + (items.x) + "," + (items.y));
                if (items.startItemPathArray) {
                    items.startItemPathArray.push("C" + Math.round(settings.preControl2[i].x) + "," + Math.round(settings.startPreControl2[i].y) + 
                        " " + Math.round(settings.controlP1[i].x) + "," + Math.round(settings.startPreControl2[i].y) + 
                        " " + (items.x) + "," + (items.startY));
                    items.endItemPathArray.push("C" + Math.round(settings.preControl2[i].x) + "," + Math.round(settings.preControl2[i].y - settings.animateSpace) + 
                        " " + Math.round(settings.controlP1[i].x) + "," + Math.round(settings.controlP1[i].y - settings.animateSpace) + 
                        " " + (items.x) + "," + (items.y - settings.animateSpace));
                }
                settings.controlP2[i].x = parseInt( leftRightCP[1][0] );
                settings.controlP2[i].y = parseInt( leftRightCP[1][1] );
                settings.preControl2[i] = settings.controlP2[i];

                settings.startControlP2[i].y = parseInt(items.startY + leftRightCP[1][1] - items.y);
                settings.startPreControl2[i] = settings.startControlP2[i];
            } else if (index == items.dataLength - 1) {
                settings.lastPath = settings.lastPath || [];
                // var value = settings.data[index - 1] ? settings.data[index - 1].value[i] : settings.data[index].value[i];
                // var beforeValue = settings.data[index - 2] ? settings.data[index - 2].value[i] : settings.data[index - 1];
                // var afterValue = items.value;
                if (items.active) { //如果是添加操作
                    items.itemPathArray[items.itemPathArray.length - 1] = settings.lastPath[i];
                }

                var leftRightCP = _getPathPosition(settings, items);
                settings.controlP1[items.i].x = parseInt( leftRightCP[0][0] );
                settings.controlP1[items.i].y = parseInt( leftRightCP[0][1] );

                items.itemPathArray.push("C" + Math.round(settings.preControl2[i].x) + "," + Math.round(settings.preControl2[i].y) + " " + (items.x) + "," + (items.y) + " " + (items.x) + "," + (items.y));
                if (items.startItemPathArray) {
                    items.startItemPathArray.push("C" + Math.round(settings.preControl2[i].x) + "," + Math.round(settings.startPreControl2[i].y) + " " + (items.x) + "," + (items.startY) + " " + (items.x) + "," + (items.startY));
                    items.endItemPathArray.push("C" + Math.round(settings.preControl2[i].x) + "," + Math.round(settings.preControl2[i].y - settings.animateSpace) + " " + (items.x) + "," + (items.y - settings.animateSpace) + " " + (items.x) + "," + (items.y - settings.animateSpace));
                }
                settings.lastPath[i] = ("C" + Math.round(settings.preControl2[i].x) + "," + Math.round(settings.preControl2[i].y) + " " + Math.round(settings.controlP1[i].x) + "," + Math.round(settings.controlP1[i].y) + " " + (items.x) + "," + (items.y)); //存储最后一条数据path，便于新增使用
                settings.controlP2[i].x = parseInt( leftRightCP[1][0] );
                settings.controlP2[i].y = parseInt( leftRightCP[1][1] );
                settings.preControl2[i] = settings.controlP2[i];

                settings.startControlP2[i].y = parseInt(items.startY + leftRightCP[1][1] - items.y);
                settings.startPreControl2[i] = settings.startControlP2[i];
            }
        }
    }

    function _createText(settings, items, textCx, textCy, num, i) {
        if (isSVG) {
            items.text = settings.cord.createElement("text", {
                "x": textCx,
                "y": textCy,
                "fill": settings.DOT_TEXT_FILL,
                "text-anchor": "middle"
            }, settings.gText);
            items.text.textContent = items.value;
        } else {
            items.text = $("<span></span>").css({
                "position": "absolute",
                "color": settings.DOT_TEXT_FILL
            }).text(items.value).appendTo(settings.gText);

            if ((num > 0 && i === 0) || num <= 0) {
                items.text.css({
                    "left": textCx - items.text.width(),
                    "top": textCy - items.text.height()
                });
            }
        }
    }

    //afterAddFlag:初始化之后再进行添加操作  data:数据;index:当前数据索引;active:操作状态(add/null);  type:当前操作状态(create/modify);yType:当前添加数据参照Y1/Y2
    //该方法可做添加/修改的操作
    function _addNode(settings, data, index, active, type, afterAddFlag, yType) {
        var itemsA;
        // 如果长度为0，就取当前数据集组数
        // 一般返回data.value.length长度，当前数据集合组数
        // valueLength: N(y2)
        // y1: yNum=0
        // y1+y2: yNum=N(y1)
        // 
        // create: num=0
        // modify: num= settings.itemsArray.length - 1
        var valueLength = data.value.length === 0 ? settings.cord.getValueLength(settings) : data.value.length; 
        // 设置了y1数据，并且有y2数据，那么就表示y1的组数
        // 否则0
        var yNum = (yType == "y1" && settings.dataY2Flag) ? settings.cord.getValueLength(settings) : 0;
        // 设置了y2数据，取得是y1数据集合组数
        yNum = (yType == "y2" && settings.data) ? settings.cord.getValueLength(settings) : yNum;

        // TODO: 什么用处？这里有BUG
        var num = type == "modify" ? (settings.itemsArray.length != valueLength + yNum ? settings.itemsArray.length - 1 : 0) : 0;
        var xText = data.label;

        settings._tmpPrevItemsArray = settings._tmpPrevItemsArray || [];

        // for (var i = 0; i < valueLength + num; i++) {
        for (var i = 0; i < valueLength; i++) {
            var items = {};
            var iY2 = yType == "y2" ? yNum : 0; // BUG: 双坐标轴没有考虑Y1有多组数据
            items.color = (settings.isAim && valueLength == 1) ? settings.colorArray[settings.aimLine.length] : settings.colorArray[i + iY2]; //折线颜色
            if (!settings.circleArray[i + iY2]) {
                settings.circleArray[i + iY2] = [];
            }
            itemsA = settings.itemsArray[i + iY2]; // 每组数据只有一个items
            if ((!itemsA || itemsA.itemPathArray.length === 0 || yType == "y2") && index === 0) {
                items.itemPathArray = [];
                items.startItemPathArray = [];
                items.endItemPathArray = [];
                items.itemPathArray.push("M"); // 每组数据有一个path路径数组
                items.startItemPathArray.push("M");
                items.endItemPathArray.push("M");
                settings.preControl2.push({});
                settings.startPreControl2.push({});
                settings.controlP2.push({});
                settings.controlP1.push({});
                settings.startControlP1.push({});
                settings.startControlP2.push({});
                settings.eItem.push({});
                settings.sItem.push({});
            } else {
                items.itemPathArray = itemsA.itemPathArray;
                items.startItemPathArray = itemsA.startItemPathArray;
                items.endItemPathArray = itemsA.endItemPathArray;
            }
            items.active = active;
            items.index = index;
            items.i = i;
            items.iY2 = iY2;
            items.dataLength = settings.data.length;
            items.data = data.value;
            var v = items.proValue = num > 0 ? data.value[0] : data.value[i]; //未处理空值的初始值
            var reNum = /^\d*$/;
            items.value = ((v && !isNaN(v) && reNum.test(v)) || (parseInt(v) === 0) || typeof v == "number") ? items.proValue : settings.emptyValue;
            items.label = xText;

            // TODO: 应该把 + settings.padding放到poses计算的位置
            items.x = !settings.orientation ? Math.round(settings.xPoses[index] + settings.padding) : settings.yPoses[index].value[i] + settings.padding;
            items.y = !settings.orientation ? settings.yPoses[index].value[i] + settings.padding : Math.round(settings.xPoses[index] + settings.padding);
            var y = !settings.orientation ? settings.height : 0;

            items.startY = (!settings.orientation && settings._zeroY1 !== undefined) ? (settings._zeroY1 + settings.padding) : (settings.height + settings.padding * 2);
            items.endY = items.y - settings.animateSpace;

            if (index === 0 && settings.isAreaLine(i + iY2)) {
                settings.sItem[i] = items;
            }
            if (index == settings.data.length - 1 && settings.isAreaLine(i + iY2)) {
                settings.eItem[i] = items;
            }

            _getItemPath(settings, items);
            settings._tmpPrevItemsArray[i+iY2] = items; // 保存起来在_getItemPath备用

            if (type == "create") {
                var cx = items.x;
                var cy = items.y;
                var color = ((v && !isNaN(v) && reNum.test(v)) || (parseInt(v) === 0) || typeof v == "number") ? items.color : settings.emptyColor;
                //如果显示圆点
                if (settings.isCircle) {
                    //创建圆点对象
                    items.circle = settings.cord.createElement("circle", {
                        "cx": cx,
                        "cy": cy,
                        "value": items.value,
                        "r": settings.circleR,
                        "fill": settings.circleFillColor,
                        "stroke": color,
                        "stroke-width": 2, 
                        'stroke-opacity': settings.circleStrokeOpacity
                    }, settings.gCircle);



                    if (!isSVG && settings.circleStrokeOpacity < 1) {
                        settings.cord.createElement("stroke", {
                            "opacity": settings.circleStrokeOpacity
                        }, items.circle);
                    }
                }
                if (settings.isShowText) {
                    var textCx = !settings.orientation ? cx : cx + 15;
                    var textCy = !settings.orientation ? cy - 8 : cy + 4;
                    _createText(settings, items, textCx, textCy, num, i);
                }
            } else {
                if (settings.isShowText) {
                    var circleItem = settings.circleArray[i + iY2][index];
                    items.text = circleItem ? circleItem.text : null;
                    
                    if (isSVG) {
                        circleItem.text.textContent = items.value;
                    } else {
                        circleItem && circleItem.text && circleItem.text.text(items.value); // IE BUG
                    }
                }
            }
            items.itemPath = items.itemPathArray.join("");
            items.startItemPath = items.startItemPathArray.join("");
            items.endItemPath = items.endItemPathArray.join("");
            if (settings.isAreaLine(i + iY2)) {
                items.itemPathSolid = items.itemPathArray.join("");
                items.startItemPathSolid = items.startItemPathArray.join("");
                items.endItemPathSolid = items.endItemPathArray.join("");
            }
            if ((index == settings.data.length - 1) && settings.isAreaLine(i + iY2)) {
                var sPoint = settings.orientation ? {
                    x: settings.padding,
                    y: settings.sItem[i].y
                } : {
                    x: settings.sItem[i].x,
                    y: y + settings.padding
                };
                var ePoint = settings.orientation ? {
                    x: settings.padding,
                    y: settings.eItem[i].y
                } : {
                    x: settings.eItem[i].x,
                    y: y + settings.padding
                };

                // 需要根据Y轴的值来计算零点的位置
                if (settings._zeroY1 !== undefined) {
                    ePoint.y = sPoint.y = settings._zeroY1 + settings.padding;
                }

                var closeSubPath = 'L' + ePoint.x + ',' + ePoint.y + 'L' + sPoint.x + ',' + sPoint.y + 'Z';
                
                items.itemPath += closeSubPath;
                items.startItemPath += closeSubPath;
                items.endItemPath += closeSubPath;
            }
            if ((!itemsA || itemsA.itemPathArray.length === 0 || yType == "y2") && index === 0) {
                if (type == "modify") {
                    settings.itemsArray[i + iY2].itemPathArray = items.itemPathArray;
                    settings.itemsArray[i + iY2].itemPath = items.itemPath;
                    settings.itemsArray[i + iY2].itemPathSolid = items.itemPathSolid;
                    settings.itemsArray[i + iY2].startItemPathArray = items.startItemPathArray;
                    settings.itemsArray[i + iY2].startItemPath = items.startItemPath;
                    settings.itemsArray[i + iY2].startItemPathSolid = items.startItemPathSolid;
                    settings.itemsArray[i + iY2].endItemPathArray = items.endItemPathArray;
                    settings.itemsArray[i + iY2].endItemPath = items.endItemPath;
                    settings.itemsArray[i + iY2].endItemPathSolid = items.endItemPathSolid;
                } else if (type == "create") {
                    var fillColor = settings.isAreaLine(i + iY2) ? items.color : 'none';
                    //创建折线
                    items.line = settings.cord.createElement("path", {
                        "fill": fillColor,
                        "stroke": items.color,
                        "cursor": "pointer"
                    }, settings.gLine);
                    if (!settings.isAreaLine(i+iY2)) {
                        settings.cord.setAttributes(items.line, {
                            "filled": "f"
                        });
                    }
                    if (settings.dashArray && settings.dashArray[i] === true && !settings.isAreaLine(i + iY2)) {
                        settings.cord.setAttributes(items.line, {
                            "stroke-dasharray": "2,2"
                        });
                    }
                    if (settings.isAreaLine(i+iY2)) {
                        items.lineSolid = settings.cord.createElement("path", {
                            "d": items.itemPathSolid,
                            "fill": "none",
                            "stroke": items.color,
                            "stroke-width": settings.strokeWidth,
                            "ostroke-width": settings.strokeWidth,
                            "cursor": "pointer",
                            "filled": "f"
                        }, settings.gLine);
                        settings.cord.setAttributes(items.line, {
                            "opacity": settings.opacity
                        });
                        if (settings.dashArray && settings.dashArray[i] === true) {
                            settings.cord.setAttributes(items.lineSolid, {
                                "stroke-dasharray": "2,2"
                            });
                        }
                    } else {
                        settings.cord.setAttributes(items.line, {
                            "stroke-width": settings.strokeWidth,
                            "ostroke-width": settings.strokeWidth
                        });
                    }
                    settings.itemsArray.push(items);
                }

                if (settings.circleArray[i + iY2].length < settings.data.length) {
                    settings.circleArray[i + iY2].push(items);
                }
            } else {
                if (type == "modify" || afterAddFlag || !settings.isAnimate) {
                    settings.cord.setAttributes(itemsA.line, {
                        "d": items.itemPath
                    });
                    if (settings.isAreaLine(i + iY2)) {
                        settings.cord.setAttributes(itemsA.lineSolid, {
                            "d": items.itemPathSolid
                        });
                    }
                }

                $(itemsA.line).children("animate").remove();

                itemsA.itemPath = items.itemPath;
                itemsA.startItemPath = items.startItemPath;
                itemsA.endItemPath = items.endItemPath;
                if (settings.isAreaLine(i + iY2)) {
                    itemsA.itemPathSolid = items.itemPathSolid;
                    itemsA.startItemPathSolid = items.startItemPathSolid;
                    itemsA.endItemPathSolid = items.endItemPathSolid;
                    $(itemsA.lineSolid).children("animate").remove();
                }
                if (settings.circleArray[i + iY2].length < settings.data.length) {
                    settings.circleArray[i + iY2].push(items);
                }
                if (settings.isCircle) {
                    $(settings.circleArray[i + iY2][index].circle).children("animate").remove();
                }
                if (settings.isShowText) {
                    $(settings.circleArray[i + iY2][index].text).children("animate").remove();
                }
            }

            //更新圆点位置
            if (settings.circleArray[i + iY2][index] && type == "modify") {
                settings.circleArray[i + iY2][index].x = items.x;
                settings.circleArray[i + iY2][index].y = items.y;
                settings.circleArray[i + iY2][index].value = items.value;
            }

            if (type == "modify" || afterAddFlag) {
                var cx = items.x;
                var cy = items.y;
                if (settings.isCircle) {
                    items.circle = settings.circleArray[i + iY2][index].circle;
                    settings.cord.setAttributes(items.circle, {
                        "cx": cx,
                        "cy": cy
                    });
                }
                if (settings.isShowText) {
                    var textCx = !settings.orientation ? cx : cx + 15;
                    var textCy = !settings.orientation ? cy - 8 : cy + 4;
                    var circleItem = settings.circleArray[i + iY2][index];
                    
                    if (isSVG) {
                        settings.cord.setAttributes(circleItem.text, {
                            "x": textCx,
                            "y": textCy
                        });
                    } else {
                        circleItem.text && circleItem.text.css({
                            left: textCx - circleItem.text.width()/2,
                            top: textCy - circleItem.text.height()/2
                        });
                    }
                }
            } else {
                if (settings.isAnimate) {
                    if (settings.isCircle) {
                        $(settings.circleArray[i + iY2][index].circle).css("opacity", 0);
                    }
                    if (settings.isShowText) {
                        $(settings.circleArray[i + iY2][index].text).css("opacity", 0);
                    }
                }
            }
            if (typeof settings.onCreateItem == "function") {
                settings.onCreateItem(items);
            }
        }

        if (active == "add" && type == "create" && settings.isAim) {
            for (var i = 1; i < settings.aimLineArray.length + 1; i++) {
                var itemO = settings.itemsArray[0];
                var itemObj = settings.itemsArray[i];
                settings.cord.setAttributes(itemObj.line, {
                    "d": itemO.itemPath
                });
                $(itemObj.line).children("animate").remove();

                if (settings.isAreaLine(i)) { // TODO
                    settings.cord.setAttributes(itemObj.lineSolid, {
                        "d": itemO.itemPathSolid
                    });
                    $(itemObj.lineSolid).children("animate").remove();
                }

                var cItems = {};
                var cItemO = settings.circleArray[0][settings.circleArray[0].length - 1];
                var color = settings.colorArray[i - 1]; //折线颜色
                cItems.x = cItemO.x;
                cItems.y = cItemO.y;
                cItems.endY = cItemO.endY;
                cItems.startY = cItemO.startY;
                cItems.value = cItemO.value;
                cItems.color = color;
                var cx = cItemO.x;
                if (settings.isCircle) {
                    cItems.circle = settings.cord.createElement("circle", {
                        "cx": cx,
                        "cy": cItemO.y,
                        "value": cItemO.value,
                        "r": 3,
                        "fill": settings.circleFillColor,
                        "stroke": cItems.color,
                        "stroke-width": 2
                    }, itemObj.gCircle);
                    if (!afterAddFlag && settings.isAnimate) {
                        $(cItems.circle).css("opacity", 0);
                    }
                }
                if (settings.isShowText) {
                    var textCx = !settings.orientation ? cx : cx + 15;
                    var textCy = !settings.orientation ? cItems.y - 8 : cItems.y + 4;
                    
                    if (isSVG) {
                        cItems.text = settings.cord.createElement("text", {
                            "x": textCx,
                            "y": textCy,
                            "fill": settings.DOT_TEXT_FILL,
                            "text-anchor": settings.DOT_TEXT_ANCHOR
                        }, itemObj.gText);
                        if (!afterAddFlag && settings.isAnimate) {
                            $(cItems.text).css("opacity", 0);
                        }
                        cItems.text.textContent = cItemO.value;
                    }
                }
                settings.circleArray[i].push(cItems);
            }
        }
    }

    function _selectCrossItem(settings, params, index) {
        $(settings.gCross).show();
        params.crossObj.show();
        settings.cord.select(index);
    }

    function _unselectCrossItem(settings, params) {
        if (!settings.gCross || !settings.cord || !settings.cord._settings) { return; }
        settings.gCross.style.display = "none";
        params.crossObj.hide();
        if (params.crossMouseLeave && typeof params.crossMouseLeave == "function") {
            params.crossMouseLeave(params.crossObj, settings.circleArray);
        }
        settings.cord.unselect();
    }

    //是否启用十字坐标线功能
    function _enableCross(settings, flag, options) {
        var params = $.extend({
            container: null, //容器
            hoverObj: null, //事件对象
            crossObj: null, //十字坐标线Tip提示对象
            crossMouseMove: null, //MouseMove回调
            crossMouseLeave: null //MouseOut回调        
        }, options || {});
        if (!flag) {
            $(params.hoverObj).unbind("mousemove").unbind("mouseleave");
        } else {
            if (!settings.gCross) {
                settings.gCross = settings.cord.createElement("g", null, params.container);
                $(settings.gCross).css({
                    "-webkit-transition": settings.TRANSITION
                });
                settings.lineCross = settings.cord.createElement("path", {
                    "d": "M0,0L0,0",
                    stroke: settings.crossLineColor
                }, settings.gCross);

                if (settings.colorArray.length === 0) {
                    _setColor(settings);
                }

                // TODO: buggy, 这里的颜色数组并不是我们取多少就会有多少，导致crossArray长度和数据长度不一致
                // var cLength = settings.isAim ? 1 : settings.colorArray.length; 
                var cLength = settings.circleArray.length; // 因为#1622有关联操作

                //创建十字坐标对象并存储
                for (var n = 0; n < cLength; n++) {
                    var items = {};
                    var color = settings.colorArray[n]; //图例颜色
                    items.circle = settings.cord.createElement("circle", {
                        "cx": 0,
                        "cy": 0,
                        "r": settings.crossCircleRadius,
                        "fill": settings.crossCircleFill,
                        "stroke": color,
                        "stroke-width": settings.crossCircleStrokeWidth
                    }, settings.gCross);
                    items.circleSelect = settings.cord.createElement("circle", {
                        "cx": 0,
                        "cy": 0,
                        "r": settings.crossCircleSelectRadius,
                        "fill": color,
                        "stroke": color,
                        "stroke-width": settings.crossCircleStrokeWidth
                    }, settings.gCross);
                    settings.crossArray.push(items);
                }
            }
            settings.gCross.style.display = "none";
            params.hoverObj.unbind("mousemove").bind("mousemove", function(e) {
                var xSpaceWidth = settings.xPoses[1] - settings.xPoses[0];

                if (settings.isLineHover && !settings.isArea) { // TODO: why?
                    return;
                }
                var scrollLeft = settings.cord._settings.scrollLeft;
                var first = parseInt(settings.circleArray[0][0].x / xSpaceWidth) * xSpaceWidth;
                var objLeft = settings.orientation ? $(settings.frags).offset().top : $(settings.frags).offset().left;
                var x = settings.orientation ? (e.pageY - parseInt(objLeft) - scrollLeft) : (e.pageX - parseInt(objLeft) - scrollLeft);
                var fNum = settings.isSide ? 0 : 1; //如果不是贴边显示fNum为1;
                var index = Math.ceil((x - xSpaceWidth / 2) / xSpaceWidth) - fNum || 0;
                var num = xSpaceWidth / 3;
                var num2 = xSpaceWidth / 2;

                for (var i = 0; i < settings.crossArray.length; i++) {
                    // TODO: bug, 当只有一组数据的时候，如果设置了crossArray就会报错
                    // var cLength = settings.circleArray[i] ? settings.circleArray[i].length : 0; 
                    var cLength = settings.circleArray[i].length; 
                    if (index > cLength - 1) {
                        index = cLength - 1;
                    }
                    if (index < 0) {
                        index = 0;
                    }
                    var cx = settings.circleArray[i][index].x;
                    var cy = settings.circleArray[i][index].y;

                    if (!settings.isCrossTypeShow) {
                        if (settings.orientation) {
                            if (x <= cy - num || cy <= x - num) {
                                settings.gCross.style.display = "none";
                                params.crossObj.hide();
                                return;
                            }
                        } else {
                            if (x + first <= cx - num || cx <= x - num) {
                                settings.gCross.style.display = "none";
                                params.crossObj.hide();
                                return;
                            }
                        }
                    }

                    settings.cord.setAttributes(settings.crossArray[i].circle, {
                        "cx": cx,
                        "cy": cy
                    });
                    settings.cord.setAttributes(settings.crossArray[i].circleSelect, {
                        "cx": cx,
                        "cy": cy
                    });

                    var lineCx = cx;
                    if (settings.orientation) {
                        settings.cord.setAttributes(settings.lineCross, {
                            "d": "M0," + cy + "L" + settings.width + "," + cy,
                            "stroke-width": 1
                        });
                    } else {
                        settings.cord.setAttributes(settings.lineCross, {
                            "d": "M" + lineCx + "," + (-parseInt($(settings.svg).css("top"))) + "L" + lineCx + "," + (settings.height + settings.padding),
                            "stroke-width": 1
                        });
                    }

                    $(settings.crossArray[i].circle).bind(settings.Source.MOUSEMOVE, function() {
                        _selectCrossItem(settings, params, index);
                    });
                }
                if (e.pageX + 20 + params.crossObj.outerWidth(true) >= $("body").width()) {
                    params.crossObj.css({
                        left: ($("body").width() - params.crossObj.outerWidth(true)) + "px",
                        top: e.pageY + 10
                    });
                } else {
                    params.crossObj.css({
                        left: e.pageX + 20,
                        top: e.pageY + 10
                    });
                }
                _selectCrossItem(settings, params, index);
                if ($.isFunction(params.crossMouseMove)) {
                    if (settings.isAim) {
                        var circleArray = [];
                        circleArray.push(settings.circleArray[0]);
                        params.crossMouseMove.call(settings, params.crossObj, circleArray, index, settings.gCross);
                    } else {
                        params.crossMouseMove.call(settings, params.crossObj, settings.circleArray, index, settings.gCross);
                    }
                }
            }).bind("mouseleave", function(e) {
                _unselectCrossItem(settings, params);
            });
            $("body").bind(settings.Source.MOUSEMOVE, function(e) {
                var targLength = $(e.target).parents(".Frags").length;
                var legendLength = $(e.target).parents(".legend").length;
                if (targLength === 0 && legendLength === 0) {
                    _unselectCrossItem(settings, params);
                }
            });
        }
    }

    function _infoLayer(settings, tip) {
        settings.infoLayer.show();
        settings.infoLayer.html(tip);
    }

    function _setCords(settings, onCreateMark, type) {
        var data = settings.data;
        if (!(data instanceof Array)) {
            return;
        }
        settings.cord._settings.frags = settings.frags;
        var dataY2Num = settings.dataY2Flag ? settings.dataY2[0].value.length : 0;
        //设置图例，如果数据类型只有一种则不显示图例
        if (data && settings.cord.getValueLength(settings) + dataY2Num > 1 && settings.legendData && settings.cord._settings.legendArray.length === 0) {
            settings.cord.setLegend(settings.legendData);
        }
        var dLength = settings.xCount ? settings.xCount : settings.data.length;
        //设置X轴数据
        settings.cord.setDataMark(settings.orientation, dLength, function(dot, index, poses) {
            if (typeof onCreateMark == 'function') {
                onCreateMark.call(settings.self, dot, index, poses);
            }
        }, type);
        var blank = 2;
        var itemM = _getMaxMin(settings, data);
        var min = itemM.min;
        var max = itemM.max;
        if (settings.y1Data) {
            var itemRM = settings.cord.repairMaxMin(settings, settings.y1Data, max, min);
            min = itemRM.min;
            max = min < 0 ? itemRM.max + Math.abs(min) : itemRM.max; //如果最小值为负值，最大值将加上最小值
        }
        //设置Y1坐标数据，对比Y轴数据和数据源取出最大值
        settings.cord.setYCord1(max, settings.y1Data, function(dot, index) {
            dot.html(settings.y1Data[index]);
            if (typeof settings.y1MarkOnCreakMark == "function") {
                settings.y1MarkOnCreakMark(dot, index);
            }
            if (dot.html() === "") {
                dot.width(0);
            }
        }, min);
        var maxY2 = null,
            minY2 = null;
        if (settings.dataY2Flag) {
            var itemMY2 = _getMaxMin(settings, settings.dataY2);
            var y2data = (settings.orientation && settings.y2Data) ? settings.cord.getMainPoses(settings.data.length) : settings.y2Data;

            var max2 = (y2data instanceof Array) ? settings.cord.repairMaxMin(settings, y2data, itemMY2.max, itemMY2.min) : 0;

            minY2 = max2.min;
            maxY2 = minY2 < 0 ? max2.max + Math.abs(minY2) : max2.max; //如果最小值为负值，最大值将加上最小值
        }
        //设置Y2坐标数据，对比Y轴数据和数据源取出最大值
        settings.cord.setYCord2(maxY2 === null ? max : maxY2, settings.y2Data, function(dot, index) {
            if (typeof settings.y2MarkOnCreakMark == "function") {
                settings.y2MarkOnCreakMark(dot, index);
            }
        }, minY2 === null ? min : minY2);
        settings.cord.setFragsSize(settings);
        //设置X/Y轴的网格线
        if (!settings.isComPlex && settings.isGrid) {
            settings.cord.setXGrid(settings.frags, max, settings.y1Data, null, min, settings.isInterlay);
        }
        if (!settings.isComPlex && settings.isYGrid) {
            settings.cord.setYGrid(settings.frags, settings.gridYCount);
        }
    }

    function _getMaxMin(settings, data) {
        var items = {
            max: 0,
            min: 0
        };
        for (var i = 0; i < data.length; i++) {
            var total = 0;
            if (!data[i].value) {
                continue;
            }
            for (var j = 0; j < data[i].value.length; j++) {
                var value = parseFloat(data[i].value[j]);
                if (items.max < value) {
                    items.max = value;
                }
                if (items.min > value) {
                    items.min = value;
                }
            }
        }
        return items;
    }

    /*
     *data：可传数组/可传单个值
     *根据数据及Y轴的数据计算出note对象的Y坐标
     *Y坐标计算方法：value/maxValue*height
     */
    function _getTall(settings, data, yData) {
        if (!data) {
            return null;
        }
        var datas = (data && typeof data == "object" && data.length > 0) ? data : settings.data;
        yData = (data && typeof data == "object" && data.length > 0) ? yData : settings.y1Data;

        var isY2 = yData !== settings.y1Data, firstNumY = isY2 ? 'firstNumY2' : 'firstNumY1';

        var itemM = _getMaxMin(settings, datas);
        var min = itemM.min;
        var max = itemM.max; //如果最小值为负值，最大值将加上最小值

        var itemsRM = settings.cord.repairMaxMin(settings, yData, max, min);
        min = itemsRM.min;
        max = min < 0 ? itemsRM.max + Math.abs(min) : itemsRM.max; //如果最小值为负值，最大值将加上最小值
        max = settings.eMax > 0 ? settings.eMax : max;

        var total = settings.width;
        if (!settings.orientation) {
            total = settings.height;
        }

        function _calcTall(value) {
            var tall = settings.cord.getTransValue(value, max, total, min, settings.cord._settings[firstNumY]);
            if (!settings.orientation) {
                tall = total - tall;
            }
            return tall;
        }

        // calc zero position
        settings._zeroY1 = min < 0 ? _calcTall(0) : undefined;

        var tmp = [];
        if (data && typeof data == "object" && data.length > 0) {
            for (var i = 0; i < data.length; i++) {
                var item = {
                    value: []
                };
                if (!data[i].value) {
                    data[i].value = [];
                }
                var valueLength = data[i].value.length === 0 ? settings.cord.getValueLength(settings) : data[i].value.length;
                for (var j = 0; j < valueLength; j++) {
                    var v = data[i].value[j];
                    var reNum = /^\d*$/;
                    var value = ((v && !isNaN(v) && reNum.test(v)) || (parseInt(v) === 0) || typeof v == "number") ? parseFloat(v) : parseFloat(settings.emptyValue); //1000
                    item.value.push( _calcTall(value) );
                }
                tmp.push(item);
            }
        } else {
            return _calcTall(data);
        }
        return tmp;
    }

    /**
     *数据重置时调用该方法
     * @param settings
     * @param data 数据源
     * @param yType Y轴类型(y1/y2)
     */
    function _relayout(settings, data, yType) {
        if (!(data instanceof Array)) {
            return;
        }
        if (yType == "y1") {
            if (settings.extend && settings.isSetY1Data) {
                settings.extend.empty();
                settings.cord.unselectCord();
            }
            settings.scrollLeft = settings.cord._settings.scrollLeft = -settings.padding;
            settings.cord._settings.cordContent.css("left", 0);
            _setCords(settings, settings.onCreateMark, "modify");
            settings.width = settings.frags.width();
            settings.height = (settings.isNoBeyond && !settings.orientation) ? (settings.frags.height() + (settings.cord._settings.totalNum || 0)) : settings.frags.height();
            settings.cord.setAttributes(settings.svg, {
                width: settings.container.outerWidth(true),
                height: settings.height + settings.padding * 2
            });
            var top = (settings.isNoBeyond && !settings.orientation) ? -settings.cord._settings.totalNum : 0;
            $(settings.svg).css({
                "left": -settings.padding,
                "top": top - settings.padding
            }).attr("leftAttr", -settings.padding);

            for (var j = 0; j < settings.itemsArray.length; j++) {
                settings.itemsArray[j].itemPathArray = [];
            }

            settings.xPoses = settings.cord.getMainPoses(data.length); //获取X坐标集
            settings.xSpaceWidth = settings.xPoses[1] - settings.xPoses[0];
            settings.firstPoses = settings.xPoses[0];
            settings.yPoses = _getTall(settings, data, settings.y1Data);
        } else {
            settings.yPoses = _getTall(settings, data, settings.y2Data);
        }

        _addYPoses(settings);

        settings._bbox = _calcBBox(settings.xPoses, settings.yPoses, settings.padding);

        for (var i = 0; i < data.length; i++) {
            _addNode(settings, data[i], i, null, "modify", null, yType);
        }
        _modifyAimLine(settings);
    }

    function _calcBBox(xPoses, yPoses, padding) {
        var xPos, 
            yPos, pos, 
            len = xPoses ? xPoses.length : 0, 
            bbox = [Infinity, Infinity, -Infinity, -Infinity];

        for (var i = 0; i < len; i++) {
            xPos = xPoses[i];
            yPos = yPoses[i] && yPoses[i].value;

            if (xPos < bbox[0]) {
                bbox[0] = xPos;
            }
            if (xPos > bbox[2]) {
                bbox[2] = xPos;
            }

            for (var j = 0, jlen = yPos ? yPos.length : 0; j < jlen; j++) {
                pos = yPos[j];

                if (pos < bbox[1]) {
                    bbox[1] = pos;
                }
                if (pos > bbox[3]) {
                    bbox[3] = pos;
                }
            }
        }

        bbox[0] += padding;
        bbox[1] += padding;
        bbox[2] += padding;
        bbox[3] += padding;

        return bbox;
    }

    function _addYPoses(settings) {
        if (settings.aimLineArray && settings.aimLineArray.length !== 0) {
            for (var n = 0; n < settings.yPoses.length; n++) {
                var value = settings.yPoses[n].value[0];
                $(settings.aimLineArray).each(function(index, element) {
                    settings.yPoses[n].value.push(value);
                });
            }
        }
    }

    function _dotFire(settings, self, index, over, out, i) {
        $(self.circle).unbind("hover")
            .hover(function(e) {
                if ($(settings.itemsArray[i].line).attr("state") != "click") {
                    settings.cord.setAttributes(this, {
                        "r": settings.circleRSelect
                    });
                }
                if (over && typeof over == "function") {
                    over(e, this, index, i);
                }
            }, function(e) {
                if ($(settings.itemsArray[i].line).attr("state") != "click") {
                    settings.cord.setAttributes(this, {
                        "r": settings.circleR
                    });
                }
                if (out && typeof out == "function") {
                    out(e, this, index, i);
                }
            });
    }

    function _lineFire(self, settings, itemsArray, over, out) {
        $(itemsArray).each(function(index, element) {
            $(itemsArray[index].line).unbind("mouseover").unbind("mouseout")
                .mouseover(function(e) {
                    e.stopPropagation();
                    index = settings.isAim ? -1 : index;
                    self.select(index);
                    if (over && typeof over == "function") {
                        over(this, index);
                    }
                    settings.isLineHover = true;
                })
                .mouseout(function(e) {
                    e.stopPropagation();
                    index = settings.isAim ? -1 : index;
                    if ($(this).attr("state") != "click") {
                        self.unselect(index);
                    }
                    if (out && typeof out == "function") {
                        out(this, index);
                    }
                    settings.isLineHover = false;
                });
        });
    }

    //根据索引设置图表元素是否显示隐藏
    function _setByIndex(settings, type, index) {
        settings.hiddenIndexes[index] = type !== 'show';

        for (var i = 0; i < settings.itemsArray.length; i++) {
            if (index == i) {
                if (type == "show") {
                    $(settings.itemsArray[i].line).show();
                    if (settings.isAreaLine(i)) {
                        $(settings.itemsArray[i].lineSolid).show();
                    }
                } else {
                    $(settings.itemsArray[i].line).hide();
                    if (settings.isAreaLine(i)) {
                        $(settings.itemsArray[i].lineSolid).hide();
                    }
                }

                for (var j = 0; j < settings.circleArray[i].length; j++) {
                    if (type == "show") {
                        $(settings.circleArray[i][j].circle).show();
						$(settings.circleArray[i][j].text).show();
                    } else {
                        $(settings.circleArray[i][j].circle).hide();
						$(settings.circleArray[i][j].text).hide();
                    }
                }

                // 只有当打开了十字线功能才支持显示和隐藏
                if (settings.crossArray && settings.crossArray.length) {
                    if (type == "show") {
                        $(settings.crossArray[i].circle).show();
                        $(settings.crossArray[i].circleSelect).show();
                    } else {
                        $(settings.crossArray[i].circle).hide();
                        $(settings.crossArray[i].circleSelect).hide();
                    }
                }
            }
        }
    }

    //存储颜色
    function _setColor(settings) {
        if (!settings.isComPlex) {
            var valueLength = settings.cord.getValueLength(settings) === 0 ? 1 : settings.cord.getValueLength(settings);
            settings.isAim = valueLength != 1 ? false : settings.isAim; // TODO: buggy, 会让原始设置的值无效
            if (valueLength == 1 && settings.isAim) {
                valueLength = valueLength + settings.aimLine.length;
            }
            valueLength = settings.dataY2Flag ? valueLength + settings.dataY2[0].value.length : valueLength;
            settings.colorArray = settings.colorArray || NS.getColors(valueLength);
        }
    }

    function _updateStrokeOpacity(settings, circleElem, strokeOpacity) {
      if (isSVG) {
        settings.cord.setAttributes(circleElem, {
          "stroke-opacity": strokeOpacity
        });
      } else {
        var strokeElem = circleElem.childNodes && circleElem.childNodes.length ? circleElem.childNodes[0] : null;

        if (strokeElem) {
          settings.cord.setAttributes(strokeElem, {
            "opacity": strokeOpacity
          });
        }
      }
    }


    /** @lends UCD.Line.prototype */
    NS.Line.prototype = {
        constructor: NS.Line,
        /**
         * 初始化图表组件
         * 
         * @param  {String} type "create" || "modify" || "resize"
         */
        init: function(type) {
            var settings = this._settings;
            if (settings.itemsArray.length === 0) {
                settings.itemsArray = []; //存储折线数据
                settings.circleArray = []; //存储圆点数据
                //该方法创建公共功能(图例、X轴数据、Y轴数据、网格)
                _setCords(settings, settings.onCreateMark);
                _setColor(settings); //存储颜色
                _setData(settings, settings.data, "y1");
                //启动拖拽
                if (settings.isDrag) {
                    settings.cord.enableDrag(settings, settings.xSpaceWidth, settings.frags, $(settings.svg), null, settings.onDragMark, settings.onDragBeforeMark);
                }
                if (settings.crossFlag) {
                    //是否启用十字坐标线功能
                    _enableCross(settings, settings.crossFlag, {
                        container: settings.svg,
                        hoverObj: settings.frags,
                        crossObj: settings.crossObj,
                        crossMouseMove: settings.crossMouseMove,
                        crossMouseLeave: settings.crossMouseLeave
                    });
                }
            } else {
                _relayout(settings, settings.data, "y1");
            }
            settings.isSetY1Data = false; //是否有设置Y1Data
            
            //如果有设置Y2的数据源
            if (settings.dataY2Flag) {
                if (settings.itemsArray.length < settings.cord.getValueLength(settings) + settings.dataY2[0].value.length) {
                    _setData(settings, settings.dataY2, "y2");
                } else {
                    _relayout(settings, settings.dataY2, "y2");
                }
                settings.cord.selectCord("y1", settings.colorArray[0]);
                settings.cord.selectCord("y2", settings.colorArray[settings.colorArray.length - 1]);
            }

            // 更新目标线
            for (var i = 0, len = settings.goals ? settings.goals.length : 0, goalInfo; i < len; i++) {
                goalInfo = settings.goals[i];
                settings.cord.setGoal(settings, goalInfo.value, 
                    _getTall(settings, goalInfo.value, settings.y1Data), 
                    goalInfo.color, goalInfo.hideDot, goalInfo.hideLine);
            }
        },
        /**
         * 设置图表数据
         * 
         * @param {CommonChartDataItem[]} data         data
         * @param {Function} onCreateItem onCreateItem(items) 创建每条数据时回调(items:当条数据obj对象;)
         * @param {Function} onCreateMark onCreateMark(dot, index)  创建x轴单条数据时回调(dot: 当前x轴对象; index: 当前数据索引)。
         */
        setData: function(data, onCreateItem, onCreateMark) {
            var settings = this._settings;
            settings.infoLayer.hide();
            settings.operateType = "";
            settings.data = data || [];
            settings.onCreateItem = onCreateItem;
            settings.onCreateMark = onCreateMark;
            if (!settings.onDragBeforeMark) {
                settings.cord._settings.initDataCount = !settings.cord._settings.initDataCount ? settings.data.length : settings.cord._settings.initDataCount;
            }

            if (settings.onDragMark) {
                settings.circleArray = []; //存储圆点数据
            }
        },
        /**
         * 设置Y2轴数据
         * 
         * @param {Array} data         [description]
         * @param {Function} onCreateItem onCreateItem(items) 创建每条数据时回调(items:当条数据obj对象;)
         * @param {Function} onCreateMark onCreateMark(dot, index)  创建x轴单条数据时回调(dot: 当前x轴对象; index: 当前数据索引)。
         */
        setDataY2: function(data, onCreateItem, onCreateMark) {
            var settings = this._settings;
            if (!(data instanceof Array) || data.length === 0 || !(data[0].value instanceof Array)) {
                return;
            }
            settings.onCreateItemY2 = onCreateItem;
            settings.onCreateMarkY2 = onCreateMark;
            settings.dataY2 = data;
            settings.dataY2Flag = true;
        },
        /**
         * 添加折线数据
         *
         * @param {Object} data  折线数据 {value}
         * @param {Array} xData X轴文本数据
         */
        addNode: function(data, xData) {
            var settings = this._settings;
            settings.data.push(data);

            var x = settings.xSpaceWidth * (settings.data.length - 1) + settings.xPoses[0];
            settings.xPoses.push(x);

            var obj = {
                value: []
            };
            for (var i = 0; i < data.value.length; i++) {
                var y = _getTall(settings, data.value[i]);
                if (!settings.yPoses[settings.data.length - 1]) {
                    obj.value.push(y);
                    settings.yPoses.push(obj);
                } else {
                    settings.yPoses[settings.data.length - 1].value.push(y);
                }
            }

            settings._bbox = _calcBBox(settings.xPoses, settings.yPoses, settings.padding);

            settings.cord.addNode(xData, x);

            _addNode(settings, data, settings.data.length - 1, "add", "create", true);
            $(settings.svg).css({
                "width": settings.container.outerWidth(true)
            });
            settings.operateType = "add";
        },
        /**
         * 删除折线数据
         * 
         * @param  {Number} index  删除数据的索引值,(目前只支持删除第一条数据)
         */
        removeNode: function(index) {
            var settings = this._settings;
            if (settings.data.length <= 3) {
                return;
            }

            settings.xPoses.splice(index, 1);
            settings.yPoses.splice(index, 1);
            settings.data.splice(index, 1);
            _addYPoses(settings);

            settings.cord.removeNode(index);
            _removeNode(settings, index);
            settings.operateType = "remove";
        },
        /**
         * 设置Y1轴坐标系数据
         * 
         * @param {Array} data          Y1轴坐标系数据
         * @param {Function} onCreateMark onCreateMark(dot, index) 创建Y1轴单条数据时回调(dot: 当前Y1轴对象; index: 当前数据索引)
         */
        setY1Data: function(data, onCreateMark) {
            var settings = this._settings;
            if (settings.extend) {
                settings.extend.empty();
            }
            settings.isY1 = data ? true : false;
            console.log(data);
            settings.y1Data = data.sort(function(a, b) {
                return a > b ? 1 : -1;
            }) || [];
            settings.y1MarkOnCreakMark = onCreateMark;
            var px = settings.isYRuleLine ? "1px" : "0px";
            settings.frags.css({
                "border-left-width": px
            });
            settings.isSetY1Data = true;
        },
        /**
         * 设置Y2轴坐标系数据
         * 
         * @param {Object} data         Y2轴坐标系数据
         * @param {Function} onCreateMark onCreateMark(dot, index)创建Y2轴单条数据时回调(dot: 当前Y2轴对象; index: 当前数据索引)
         */
        setY2Data: function(data, onCreateMark) {
            var settings = this._settings;
            settings.isY2 = data ? true : false;
            settings.y2Data = data.sort(function(a, b) {
                return a > b ? 1 : -1;
            }) || [];
            settings.y2MarkOnCreakMark = onCreateMark;
            var px = settings.isYRuleLine ? "1px" : "0px";
            settings.frags.css({
                "border-right-width": px
            });
        },
        /**
         * 设置网格(水平网格线)
         * 
         * @param {Boolean} isInterlay 网格是否跨行
         */
        setXGrid: function(isInterlay) {
            this._settings.isInterlay = isInterlay;
            this._settings.isGrid = true;
        },
        /**
         * 设置Y轴网格(垂直网格线)
         * 
         * @param {Number} count 网格条数
         */
        setYGrid: function(count) {
            this._settings.gridYCount = count;
            this._settings.isYGrid = true;
        },
        /**
         * 初始化设置一屏的数据条数
         * 
         * @param {Number} count 一屏的数据条数
         */
        setInitDataCount: function(count) {
            this._settings.cord._settings.initDataCount = count;
        },
        /**
         * 设置图表透明度
         * 
         * @param {Number} opacity       面积图表初始透明度
         * @param {Number} selectOpacity 面积图表选中状态时的透明度
         */
        setOpacity: function(opacity, selectOpacity) {
            this._settings.opacity = opacity ? opacity : this._settings.opacity;
            this._settings.selectOpacity = selectOpacity ? selectOpacity : this._settings.selectOpacity;
        },
        /**
         * 设置横向或纵向
         * 
         * @param {Boolean} isVertical 是否纵向
         */
        setOrientation: function(isVertical) {
            var settings = this._settings;
            settings.itemsArray = []; //存储折线数据
            settings.circleArray = []; //存储圆点数据
            if (isVertical == settings.orientation) {
                return;
            }
            if (isVertical) {
                settings.root.addClass("vertical");
            } else {
                settings.root.removeClass("vertical");
            }
            settings.orientation = isVertical;
            _setCords(settings, null, "modify");
            _setData(settings, settings.data, "y1");
            if (settings.dataY2Flag) {
                _setData(settings, settings.dataY2, "y2");
            }
        },
        /**
         * 是否为纵向
         * 
         * @return {Boolean}
         */
        getOrientation: function() {
            return this._settings.orientation;
        },
        /**
         * resize chart
         */
        resize: function() {
            var settings = this._settings;
            settings.isSetY1Data = true;

            this.init("resize");

            if (settings.crossFlag) {
                this.enableCross(settings.crossFlag, settings.crossMouseMove, settings.crossMouseLeave);
            }
        },
        /**
         * 是否启用十字坐标线功能
         * 
         * @param  {Boolean} flag            flag
         * @param  {Function} crossMouseMove  crossmousemove(crossobj, circlearray, index): Function。十字坐标线move事件回调(crossobj:十字功能tip容器对象;circlearray:圆点数据集合;index:当前索引)
         * @param  {Function} crossMouseLeave crossmouseleave(crossobj, circlearray): Function。十字坐标线leave事件回调(crossobj:十字功能tip容器对象;circlearray:圆点数据集合;index:当前索引)
         */
        enableCross: function(flag, crossMouseMove, crossMouseLeave) {
            var settings = this._settings;
            if (settings.cord._settings.Source.isPad) {
                return;
            }
            settings.crossMouseMove = crossMouseMove;
            settings.crossMouseLeave = crossMouseLeave;
            if (!settings.crossObj) {
                settings.crossObj = $("<div class='chartCross'></div>").appendTo($("body")).addClass(NS.getStyle());
            }
            settings.crossFlag = flag;
        },
        /**
         * 目标线参数
         * 如果已经存在目标线，就删除现有的。
         * 
         * @param {Object[]} goals { value: 0, color: '', hideDot: false, hideLine: false }
         */
        setGoals: function(goals) {
            var settings = this._settings;

            if (settings.goals && settings.goals.length) {
                this.removeGoals();
            }

            if (goals) {
                settings.goals = goals;
            } else {
                settings.goals = [];
            }
        }, 

        /**
         * 删除所有目标线
         */
        removeGoals: function() {
            var settings = this._settings, $extend = settings.extend;

            if ($extend) {
                $extend.children(".goal").remove();
            }

            settings.goals = [];
        }, 

        /**
         * 是否拖拽
         * 
         * @param  {Object} flag flag
         */
        enableDrag: function(flag) {
            this._settings.isDrag = flag;
        },
        /**
         * 是否使用平滑曲线
         * 
         * @param  {Boolean} [flag = true] flag
         */
        enableSmooth: function(flag) {
            var settings = this._settings;
            settings.isSmooth = flag;

            if (settings.itemsArray.length !== 0) {
                for (var j = 0; j < settings.itemsArray.length; j++) {
                    settings.itemsArray[j].itemPathArray = [];
                }
                _addYPoses(settings);
                for (var i = 0; i < settings.data.length; i++) {
                    _addNode(settings, settings.data[i], i, null, "modify");
                }
            }
        },
        /**
         * 是否启用目标线分区域块功能,支持X、Y两种情况的分区域块设置(目前只适应一条数据的情况)
         * 
         * @param  {Boolean} isAim      是否启用目标线分区域块功能。
         * @param  {Array}   aimLine     分区值。
         * @param  {String}  aimPosition "" || "Y" || "X"
         * @param  {Array}   xData       x轴数据。可选(如设置为X轴分区，必须传入)。
         */
        enableAim: function(isAim, aimLine, aimPosition, xData) {
            this._settings.isAim = isAim;
            this._settings.aimLine = aimLine || [];
            this._settings.aimPosition = aimPosition;
            this._settings.xData = xData || [];
        },
        /**
         * 折线是否添加圆点
         * 
         * @param  {Boolean} flag 是否添加圆点
         */
        enableCircle: function(flag) {
            this._settings.isCircle = flag;
        },
        /**
         * 是否显示tip文本
         * 
         * @param  {Boolean} flag flag
         */
        enableShowText: function(flag) {
            this._settings.isShowText = flag;
        },
        /**
         * 是否贴边显示
         * 
         * @param  {Boolean} flag flag
         */
        enableSide: function(flag) {
            this._settings.isSide = flag;
            this._settings.cord.enableSide(flag);
        },
        /**
         * 是否启用动画
         * 
         * @param  {Boolean} flag        flag
         * @param  {String} [animateType = "y"]  动画类型 x/y(默认为y)
         * @param  {Number} [animateTime = 2000]  animateTime
         */
        enableAnimate: function(flag, animateType, animateTime) {
            this._settings.isAnimate = flag;
            this._settings.animateType = animateType || "y";
            this._settings.animateTime = animateTime || 2000;
            if (!flag) {
                this._settings.animateType = "y";
            }
            if (flag && this._settings.animateType == "x") {
                this._settings.isAnimate = false;
            }
        },
        /**
         * 是否显示Y轴刻度
         * 
         * @param  {Boolean} flag flag
         */
        enableYRule: function(flag) {
            this._settings.cord.enableYRule(flag);
        },
        /**
         * 是否显示X轴刻度
         * 
         * @param  {Boolean} flag flag
         */
        enableXRule: function(flag) {
            this._settings.cord.enableXRule(flag);
        },
        /**
         * 是否显示Y轴标尺
         * 
         * @param  {Boolean} flag flag
         */
        enableYRuleLine: function(flag) {
            this._settings.isYRuleLine = flag;
            this._settings.cord.enableYRuleLine(flag, this._settings.orientation);
        },
        /**
         * 是否显示X轴标尺
         * 
         * @param  {Boolean} flag flag
         */
        enableXRuleLine: function(flag) {
            this._settings.cord.enableXRuleLine(flag, this._settings.orientation);
        },
        /**
         * X轴文本是否换行显示
         * 
         * @param  {Boolean} flag flag
         */
        enableLineFeed: function(flag) {
            this._settings.cord._settings.isLineFeed = flag;
        },
        /**
         * 移动显示十字线功能时是否持续显示
         * 
         * @param  {Object} [flag = false] 默认情况下如果鼠标移出一定的位置会隐藏十字线
         * @return {Object}      [description]
         */
        enableCrossTypeShow: function(flag) {
            this._settings.isCrossTypeShow = flag;
        },
        /**
         * 坐标是否上移
         * 
         * @param  {Object} flag [description]
         * @return {Object}      [description]
         */
        enableRuleMoveUp: function(flag) {
            this._settings.cord._settings.isRuleMoveUp = flag;
        },
        /**
         * 设置图例数据
         * 
         * @param {Array} data 图例数据
         */
        setLegend: function(data) {
            var settings = this._settings;
            settings.legendData = data;
        },
        /**
         * 设置图表背景颜色
         * 
         * @param {String} color 背景颜色
         */
        setFragBack: function(color) {
            if (color) {
                this._settings.frags.css("background", color);
            }
        },
        /**
         * 设置线的粗细和dot圆点的大小
         * 
         * @param {Number} [width = 2]         初始状态设置线的粗细
         * @param {Number} [selectWidth = 3]   选中状态设置线的粗细
         * @param {Number} circleR       dot半径
         * @param {Number} circleRSelect dot选中半径
         */
        setStrokeWidth: function(width, selectWidth, circleR, circleRSelect) {
            var settings = this._settings;
            if (width && width >= 0) {
                settings.strokeWidth = width || settings.strokeWidth;
                settings.strokeWidthSelect = selectWidth || settings.strokeWidthSelect;
                settings.circleR = circleR || settings.circleR;
                settings.circleRSelect = circleRSelect || settings.circleRSelect;
                for (var i = 0; i < settings.itemsArray.length; i++) {
                    if (settings.isAreaLine(i)) {
                        settings.cord.setAttributes(settings.itemsArray[i].lineSolid, {
                            "stroke-width": width,
                            "ostroke-width": width
                        });
                    } else {
                        settings.cord.setAttributes(settings.itemsArray[i].line, {
                            "stroke-width": width,
                            "ostroke-width": width
                        });
                    }
                    if (settings.isCircle && circleR && circleR > 0) {
                        for (var j = 0; j < settings.circleArray.length; j++) {
                            settings.cord.setAttributes(settings.circleArray[j][i].circle, {
                                "r": circleR
                            });
                        }
                    }
                }
            }
        },
        /**
         * 设置空值默认值和默认颜色
         * 
         * @param {Number} emptyValue 空值预设值
         * @param {String} [emptyColor = "#CCC"] 空值预设颜色
         */
        setEmpty: function(emptyValue, emptyColor) {
            this._settings.emptyValue = emptyValue || 0;
            this._settings.emptyColor = emptyColor || "#CCC";
        },
        /**
         * 设置虚线
         * 
         * @param {Array} array 设置虚线参数格式([Boolean,Boolean];Boolean位置对应折线索引)。
         */
        setDash: function(array) {
            this._settings.dashArray = array;
        },
        /**
         * 根据索引显示元素
         *
         * @param  {Number} index index
         */
        setShowByIndex: function(index) {
            _setByIndex(this._settings, "show", index);
        },
        /**
         * 根据索引隐藏元素
         *
         * @param  {Number} index index
         */
        setHideByIndex: function(index) {
            _setByIndex(this._settings, "hide", index);
        },
        /**
         * fire legend events, callbed by Coords.
         *
         * @private
         * 
         * @param  {Object}   settings settings
         * @param  {Object}   obj      obj
         * @param  {Function} fn       fn
         * @param  {String}   operate  "select" || "unselect"
         */
        _legendFire: function(settings, obj, fn, operate) {
            var index = $(obj).attr("index");
            if (operate == "select") {
                this.select(index);
            } else {
                this.unselect(index);
            }
            if (fn && typeof fn == "function") {
                fn(obj, index);
            }
        },
        /**
         * 设置图例over事件
         *
         * @event UCD.Line#setLegendOnHover
         * 
         * @param {Function} over over(obj,index) obj:当前对象;index:传出索引
         * @param {Function} out  out(obj,index) obj:当前对象;index:传出索引
         */
        setLegendOnHover: function(over, out) {
            var settings = this._settings;
            settings.cord.setLegendOnHover(settings, over, out);
        },
        /**
         * 设置图例click事件
         *
         * @event UCD.Line#setLegendOnClick
         * 
         * @param {Function} fn fn(obj,index) obj:当前对象;index:传出索引
         */
        setLegendOnClick: function(fn) {
            var settings = this._settings;
            settings.cord.setLegendOnClick(settings, fn);
        },
        /**
         * 设置dot的over/out回调
         *
         * @event UCD.Line#setDotOnHover
         * 
         * @param {Function} over over(e, obj, index): Function。dot元素的over事件回调。e:event;obj:当前对象;index:当前对象索引
         * @param {Function} out  out(e, obj, index): Function。dot元素的out事件回调。e:event;obj:当前对象;index:当前对象索引
         */
        setDotOnHover: function(over, out) {
            var settings = this._settings;
            if (settings.cord._settings.Source.isPad) {
                return;
            }
            settings.dotOnHover = over ? over : settings.dotOnHover;
            settings.dotOnOut = out ? out : settings.dotOnOut;
            if (settings.isCircle) {
                $(settings.circleArray).each(function(i) {
                    $(this).each(function(index, element) {
                        _dotFire(settings, this, index, settings.dotOnHover, settings.dotOnOut, i);
                    });
                });
            }
        },
        /**
         * 设置dot的click回调
         *
         * @event UCD.Line#setDotOnClick
         * 
         * @param {Function} fn fn(e, obj, index): function。dot元素的click事件回调。e:event;obj:当前对象;index:当前对象索引
         */
        setDotOnClick: function(fn) {
            var settings = this._settings;
            settings.dotOnClick = fn ? fn : settings.dotOnClick;
            if (settings.isCircle) {
                $(settings.circleArray).each(function(index) {
                    $(this).each(function(index, element) {
                        $(this.circle).unbind("click").click(function(e) {
                            if (settings.dotOnClick && typeof settings.dotOnClick == "function") {
                                settings.dotOnClick(e, this, index);
                            }
                        });
                    });
                });
            }
        },
        /**
         * set item on hover callback.
         *
         * @event UCD.Line#setOnHover
         * 
         * @param {Function} over 折线over(obj,index)事件 obj:当前对象;index:传出索引
         * @param {Function} out  折线out(obj,index)事件 obj:当前对象;index:传出索引
         */
        setOnHover: function(over, out) {
            var self = this;
            var settings = this._settings;
            if (settings.cord._settings.Source.isPad) {
                return;
            }
            settings.onHover = over ? over : settings.onHover;
            settings.onOut = out ? out : settings.onOut;
            _lineFire(self, settings, settings.itemsArray, settings.onHover, settings.onOut);
        },
        /**
         * set item on click callback.
         *
         * @event UCD.Line#setOnClick
         * 
         * @param {Function} fn click(obj,index)回调事件 obj:当前对象;index:传出索引
         */
        setOnClick: function(fn) {
            var self = this;
            var settings = this._settings;
            settings.onClick = fn ? fn : settings.onClick;
            $(settings.itemsArray).each(function(index) {
                $(settings.itemsArray[index].line).unbind(settings.Source.CLICK).bind(settings.Source.CLICK, function() {
                    $(settings.itemsArray).each(function(i, element) {
                        if (i != index) {
                            $(settings.itemsArray[i].line).removeAttr("state");
                            if (settings.cord._settings.legendArray.length > 0) {
                                $(settings.cord._settings.legendArray[i].gLegend).removeAttr("state");
                            }
                            self.unselect(i);
                        }
                    });
                    if ($(this).attr("state") != "click") {
                        $(this).attr("state", "click");
                    } else {
                        $(this).removeAttr("state");
                    }
                    if (settings.cord._settings.legendArray[index]) {
                        $(settings.cord._settings.legendArray[index].gLegend).attr("state", "click");
                    }
                    if (settings.onClick && typeof settings.onClick == "function") {
                        settings.onClick(this, index);
                    }
                });
            });
        },
        /**
         * 时间轴功能拖动前回调
         *
         * @event UCD.Line#setOnDragBeforeMark
         * 
         * @param {Object} onDragBeforeMark [description]
         */
        setOnDragBeforeMark: function(onDragBeforeMark) {
            this._settings.onDragBeforeMark = onDragBeforeMark;
        },
        /**
         * 时间轴功能拖动时回调
         *
         * @event UCD.Line#setOnDragMark
         * 
         * @param {Object} onDragMark [description]
         */
        setOnDragMark: function(onDragMark) {
            this._settings.onDragMark = onDragMark;
        },
        /**
         * 当添加或删除数据时，调用该方法执行滑动操作。
         */
        scrollTo: function() {
            var settings = this._settings;
            if (settings.operateType == "add") {
                if (settings.data.length <= settings.cord._settings.initDataCount) {
                    return;
                }
            } else if (settings.operateType == "remove") {
                var befNum = Math.round((Math.abs(settings.cord._settings.scrollLeft) - settings.xPoses[0]) / settings.xSpaceWidth) + 1;
                if ((settings.data.length >= settings.initDataCount && befNum >= 0) || settings.data.length <= 3) {
                    return;
                }
            }
            var left = parseInt(settings.cord._settings.cordContent.css("left")) || 0;
            settings.scrollLeft = settings.cord._settings.scrollLeft = left - settings.xSpaceWidth;
            settings.cord._settings.cordContent.css({
                "left": settings.scrollLeft,
                "-webkit-transition": ".3s ease-in-out"
            });
            $(settings.svg).css({
                "left": settings.scrollLeft,
                "-webkit-transition": ".3s ease-in-out"
            }).attr("leftAttr", settings.scrollLeft);
        },
        /**
         * [getFrags description]
         * @return {Object} 
         */
        getFrags: function() {
            return this._settings.frags;
        },
        /**
         * 选中
         *
         * @param  {Number} index index 当不传时选中所有
         */
        select: function(index) {
            var settings = this._settings;
            if (index >= 0 && index < settings.itemsArray.length) {
                if (settings.isAreaLine(index)) {
                    $(settings.itemsArray[index].line).children("animate").remove();
                    $(settings.itemsArray[index].lineSolid).children("animate").remove();
                    settings.cord.setAttributes(settings.itemsArray[index].line, {
                        "opacity": settings.selectOpacity
                    });
                } else {
                    settings.cord.setAttributes(settings.itemsArray[index].line, {
                        "stroke-width": settings.strokeWidthSelect
                    });
                }

                var circleItem = settings.circleArray[index], circleElem;

                if (circleItem && settings.isCircle) {
                    for (var i = 0; i < circleItem.length; i++) {
                        circleElem = circleItem[i].circle;

                        settings.cord.setAttributes(circleElem, {
                            "r": settings.circleRSelect
                        });

                        if (settings.circleSelectedStrokeOpacity < 1) {
                            _updateStrokeOpacity(settings, circleElem, settings.circleSelectedStrokeOpacity);
                        }
                    }
                }
                if (settings.cord._settings.legend) {
                    $(settings.cord._settings.legendArray[index].circleSelect).css({
                        "opacity": 1
                    });
                    settings.cord.setAttributes(settings.cord._settings.legendArray[index].text, {
                        "fill": settings.legendTextSelectColor
                    });
                }
            } else {
                for (var i = 0; i < settings.itemsArray.length; i++) {
                    if (settings.isAreaLine(i)) {
                        $(settings.itemsArray[i].line).children("animate").remove();
                        $(settings.itemsArray[i].lineSolid).children("animate").remove();
                        settings.cord.setAttributes(settings.itemsArray[i].line, {
                            "opacity": settings.selectOpacity
                        });
                    } else {
                        settings.cord.setAttributes(settings.itemsArray[i].line, {
                            "stroke-width": settings.strokeWidthSelect
                        });
                    }
                    if (settings.circleArray[i] && settings.isCircle) {
                        for (var j = 0; j < settings.circleArray[i].length; j++) {
                            settings.cord.setAttributes(settings.circleArray[i][j].circle, {
                                "r": settings.circleRSelect
                            });
                        }
                    }
                    if (settings.cord._settings.legend) {
                        $(settings.cord._settings.legendArray[i].circleSelect).css({
                            "opacity": 1
                        });
                        settings.cord.setAttributes(settings.cord._settings.legendArray[i].text, {
                            "fill": settings.legendTextSelectColor
                        });
                    }
                }
            }
        },
        /**
         * 取消选中
         * 
         * @param  {Number} index index 当不传时取消所有
         */
        unselect: function(index) {
            var settings = this._settings;
            if (!settings.cord || !settings.cord._settings) {
                return;
            }
            var legend = settings.isComPlex ? null : settings.cord._settings.legend;
            if (index >= 0 && index < settings.itemsArray.length) {
                var itemObj;
                var flag = false;
                if (legend) {
                    itemObj = $(settings.cord._settings.legendArray[index].gLegend);
                    if (!itemObj.attr("state")) {
                        $(settings.cord._settings.legendArray[index].circleSelect).css({
                            "opacity": 0
                        });
                        settings.cord.setAttributes(settings.cord._settings.legendArray[index].text, {
                            "fill": settings.legendTextColor
                        });
                        flag = true;
                    }
                }

                if (flag || !legend) {
                    if (settings.isAreaLine(index)) {
                        settings.cord.setAttributes(settings.itemsArray[index].line, {
                            "opacity": settings.opacity
                        });
                    } else {
                        settings.cord.setAttributes(settings.itemsArray[index].line, {
                            "stroke-width": settings.strokeWidth
                        });
                    }
                    if (settings.circleArray[index] && settings.isCircle) {
                        var circleItem = settings.circleArray[index], circleElem;

                        for (var j = 0; j < circleItem.length; j++) {
                            circleElem = circleItem[j].circle;

                            settings.cord.setAttributes(circleElem, {
                                "r": settings.circleR
                            });

                            if (settings.circleStrokeOpacity < 1) {
                                _updateStrokeOpacity(settings, circleElem, settings.circleStrokeOpacity);
                            }
                        }
                    }
                }
            } else {
                for (var i = 0; i < settings.itemsArray.length; i++) {
                    if (settings.isAreaLine(i)) {
                        if (legend) {
                            itemObj = $(settings.cord._settings.legendArray[i].gLegend);
                            if (!itemObj.attr("state")) {
                                settings.cord.setAttributes(settings.itemsArray[i].line, {
                                    "opacity": settings.opacity
                                });
                            }
                        } else {
                            settings.cord.setAttributes(settings.itemsArray[i].line, {
                                "opacity": settings.opacity
                            });
                        }
                    } else {
                        if (legend) {
                            itemObj = $(settings.cord._settings.legendArray[i].gLegend);
                            if (!itemObj.attr("state")) {
                                settings.cord.setAttributes(settings.itemsArray[i].line, {
                                    "stroke-width": settings.strokeWidth
                                });
                                $(settings.itemsArray[i].line).removeAttr("state");
                            }
                        } else {
                            settings.cord.setAttributes(settings.itemsArray[i].line, {
                                "stroke-width": settings.strokeWidth
                            });
                            $(settings.itemsArray[i].line).removeAttr("state");
                        }
                    }
                    if (settings.isAim) {
                        if (settings.circleArray[i] && settings.isCircle) {
                            for (var j = 0; j < settings.circleArray[i].length; j++) {
                                settings.cord.setAttributes(settings.circleArray[i][j].circle, {
                                    "r": settings.circleR
                                });
                            }
                        }
                        settings.cord.setAttributes(settings.itemsArray[i].line, {
                            "stroke-width": settings.strokeWidth
                        });
                        $(settings.itemsArray[i].line).removeAttr("state");
                    }
                    if (legend) {
                        var legendItem = $(settings.cord._settings.legendArray[i].gLegend);
                        if (!legendItem.attr("state")) {
                            $(settings.cord._settings.legendArray[i].circleSelect).css({
                                "opacity": 0
                            });
                            settings.cord.setAttributes(settings.cord._settings.legendArray[i].text, {
                                "fill": settings.legendTextColor
                            });
                        }
                    }
                }
            }
        },
        /**
         * 指定每组数据的折线类型
         * 
         * @param {Array} lineTypes 折线类型
         */
        setLineTypes: function(lineTypes) {
            this._settings.lineTypes = lineTypes;
        }, 
        /**
         * Destroy chart DOM, Events and Objects.
         */
        destroy: function() {
            var settings = this._settings;
            settings.self = null;
            $(settings.container).empty();
            settings.cord._settings = null;
            settings.cord = null;
            settings = null;

            TIMERS && TIMERS.clearAll();
        }
    }
})(UCD, UCD.Core);
